Generics in Method Level Java [duplicate] - java

I am trying to create a generic class in Java that will perform operations on numbers. In the following example, addition, as follows:
public class Example <T extends Number> {
public T add(T a, T b){
return a + b;
}
}
Forgive my naivety as I am relatively new to Java Generics. This code fails to compile with the error:
The operator + is undefined for the argument type(s) T, T
I thought that with the addition of "extends Number" the code would compile. Is it possible to do this Java or will I have to create overridden methods for each Number type?

Number does not have a + operator associated with it, nor can it since there is no operator overloading.
It would be nice though.
Basically, you are asking java to autobox a descedant of Number which happens to include Integer, Float and Double, that could be autoboxed and have a plus operator applied, however, there could be any number of other unknown descendants of Number that cannot be autoboxed, and this cannot be known until runtime. (Damn erasure)

Your problem is not really related to generics, rather to operators, primitives vs objects, and autoboxing.
Think about this:
public static void main(String[] args) {
Number a = new Integer(2);
Number b = new Integer(3);
Number c = a + b;
}
The above does not compile
public static void main(String[] args) {
Integer a = new Integer(2);
Integer b = new Integer(3);
Number c = a + b;
}
The above does compile, but only because of autoboxing - which is kind of a hacky syntax glue introduced in Java 5, and only works (in compile time) with some concrete types : int-Integer for example.
Behind the scenes, the Java compiler is rewriting the last statement ("I must unbox a and b to apply the sum operator with primitive datatypes, and box the result to assign it to object c") thus:
Number c = Integer.valueOf( a.intValue() + b.intValue() );
Java can't unbox a Number because it does not know at compile time the concrete type and hence it cannot guess its primitive counterpart.

You can do something like this
class Example <T extends Number> {
public Number add(T a, T b){
return new Double(a.doubleValue() + b.doubleValue());
}
}

Yes, Nathan is correct. If you want something like this, you have to write it yourself
public class Example <T extends Number> {
private final Calculator<T> calc;
public Example(Calculator<T> calc) {
this.calc = calc;
}
public T add(T a, T b){
return calc.add(a,b);
}
}
public interface Calculator<T extends Number> {
public T add(T a, T b);
}
public class IntCalc implements Calculator<Integer> {
public final static IntCalc INSTANCE = new IntCalc();
private IntCalc(){}
public Integer add(Integer a, Integer b) { return a + b; }
}
...
Example<Integer> ex = new Example<Integer>(IntCalc.INSTANCE);
System.out.println(ex.add(12,13));
Too bad Java has no type classes (Haskell) or implicit objects (Scala), this task would be a perfect use case...

There are similar questions to this one, and the answer is you can't do it like that.
You could check if a and b are an instance of Long/Double/Integer/etc. and delegate the add to methods like:
public Integer add(Integer a, Integer b) {
return a+b; // this actually uses auto boxing and unboxing to int
}
And you would need to create one for every type that extends Number, so that's not really feasible. In other words, don't use generics for numeric operations. Number as a superclass is pretty limited.

Consider Example<Number>, how would + work on that? There is no add or similar in Number or even the likes of Integer.
Worse consider final class FunkyNumber extends Number { ... weird stuff, no add op ... }.

Even the java runtime library has this problem, most of the methods dealing with primitives have to duplicate the same functionality.
The fastest option would be to write your code for one type and then copy it and replace the type to generate the methods for the other types. A short script should be enough to do this.

Related

Understanding bounded generics in java. What is the point?

I am trying to understand bounded types and not quite grasping the point of them.
There is an example of bounded generics on which provides this use case:
public class NaturalNumber<T extends Integer> {
private T n;
public NaturalNumber(T n) { this.n = n; }
public boolean isEven() {
return n.intValue() % 2 == 0;
}
// ...
}
If you are going to restrict the classes that can be the parameterized type, why not just forget the parameterization all together and have:
public class NaturalNumber {
private Integer n;
public NaturalNumber(Integer n) { this.n = n; }
public boolean isEven() {
return n.intValue() % 2 == 0;
}
// ...
}
Then any class that extends/implements Integer can be used with this class.
Also, a side question: How is T extending Integer in the first example when the Java Integer class is final?
How is T extending Integer in the first example when the Java Integer class is final?
T can only be Integer, so the "extends" here is purely symbolic. (I'm starting with the side-note because, indeed, it's an example where generics are useless. I truly have no idea why the tutorial thinks this is an informative demonstration. It's not.)
Suppose instead that T extends Number:
class Example<T extends Number> {
private T num;
void setNum(T num) { this.num = num; }
T getNum() { return num; }
}
So the point of generics in general, is that you can do this:
Example<Integer> e = new Example<>();
e.setNum( Integer.valueOf(10) );
// returning num as Integer
Integer i = e.getNum();
// and this won't compile
e.setNum( Double.valueOf(10.0) );
Generics are a form of parametric polymorphism, essentially it lets us reuse code with a generality regarding the types involved.
So what's the point of a bound?
A bound here means that T must be Number or a subclass of Number, so we can call the methods of Number on an instance of T. Number is unfortunately a generally useless base class on its own (because of precision concerns), but it might let us do something interesting like:
class Example<T extends Number> extends Number {
// ^^^^^^^^^^^^^^
...
#Override
public int intValue() {
return num.intValue();
}
// and so on
}
It's more common, for example, to find T extends Comparable<T> which lets us do something more meaningful with T. We might have something like:
// T must be a subclass of Number
// AND implement Comparable
Example<T extends Number & Comparable<T>>
implements Comparable<Example<T>> {
...
#Override
public int compareTo(Example<T> that) {
return this.num.compareTo(that.num);
}
}
And now our Example class has a natural ordering. We can sort it, even though we have no idea what T actually is inside the class body.
If we combine these concepts, that:
generics allow the "outside world" to specify an actual type and
bounds allow the "inside world" to use a commonality,
we could build constructs such as:
static <T extends Comparable<T>> T min(T a, T b) {
return (a.compareTo(b) < 0) ? a : b;
}
{
// returns "x"
String s = min("x", "z");
// returns -1
Integer i = min(1, -1);
}

Using the addition operator on a generic subclass of Number

Can someone tell me why this code gives me a compile-error?
public class Main {
public static void main(String[] args) {
System.out.println(sum(2, 6.9));
}
public static <T extends Number<T>> T sum(T a, T b) {
T result = a + b; // compile-error here
return result;
}
}
Number is not a generic class, so you can't parameterize it:
public abstract class Number implements java.io.Serializable {
...
}
Further, the + operator only works on primitive types like int, long, etc., rather than Number subtypes like Integer, Long, etc. (EDIT: It will operate on these by unboxing, yes, but it cannot automatically box the result in the appropriate wrapper class.)
(You've stumbled upon one of the reasons Number is a poor example of polymorphism. It really only performs object-to-primitive conversions.)
You can, instead create an interface with
public interface ALU <T extends Number> {
public T add(T a, T b);
}
And make your main class implementing the interface created.
public class Main implements ALU <Integer>.
And create the method add inside your main class.
public Integer add(Integer a, Integer b){
return a + b;
}
And this will work.
The error The operator + is undefined for the argument type(s) T, T is caused because The type Number is not generic; it cannot be parameterized with arguments <T>
The error highlighting in eclipse provides this information, not sure if other IDE's provide the same information.
You have to use:
a.doubleValue()+b.doubleValue()
as Number is a class and does not support the operator +

How to write a generic method in Java to support comparison and arithmetic operations

I want to write a generic method in java like below:
public <T extends Number & Comparable<T>> void test(T[] a){
T b=a[0];
if(a[0]>0){
a[0]*=a[0];
b+=a[1];
}
}
Then later, I can supply either Integer[] or Double[] or other Number subtypes to the method. But the code I tried above gives me errors.
Please help me. Thank you.
all types (including the inferred generic types) except the primitives are Objects which don't support the arithmetic operations (the wrapper classes use boxing/unboxing to get the known psuedo behavior)
and type erasure makes the compiled code use casts to get the proper behavior (i.e. at runtime the JVM doesn't know what type was passed in which it would need to know to get the proper boxing/unboxing behavior)
the only (real) solution is to provide implementations for all primitives you want to support
You can't do this in Java with generics. That's a benefit of C++ for example.
In some way you can define this as "strange", because it is possible to use operators on Java's primitive wrappers. But that is because you can't use operators on java.lang.Number, the superclass of the primitive wrappers.
Some resources:
Simple Java generics question
What are the differences between "generic" types in C++ and Java?
Can I do arithmetic operations on the Number baseclass?
Java generics and the Number class
Generic Arithmetic in Java
You've got Comparable, so if we has a zero, a[0]>0 could be replaced by a[0].compareTo(zero) > 0 (no, I think it's < 0, I can never remember). But now we've run out of useful stuff from Double and the like.
If Double and friends weren't java.lang.Comparable we could supply our own java.util.Comparator. That is we take the implementation of comparison outside of the data object. We can also do that addition and multiplication.
public interface Testor<T> { // Choose a better name...
boolean isStriclyPositive(T value);
T add(T lhs, T rhs);
T square(T value);
}
static final Testor<Integer> INTEGER_TESTOR = new Testor<>() { // Java SE 7 diamond.
public boolean isStriclyPositive(Integer value) { return value > 0; }
public Integer add(Integer lhs, Integer rhs) { return lhs + rhs; }
public Integer square(Integer value) { return value*value; }
}
// ... same for Double, etc.; can't use an enum :( ...
test(new Integer[] { 42, 1972, 86 }, INTEGER_TESTOR);
public <T> void test(T[] a, Testor<T> testor) {
T b = a[0];
if (testor.isStrictlyPositive(a[0])) {
a[0] = testor.square(a[0]);
b = testor.add(b, a[1]);
}
}
Note for things like Short, summing two of them will give you an int.
(Usual Stack Overflow disclaimer: not so much as attempted to compile the code.)

Java 5 Generics, how to get this sample working

public class Calculator<T> {
public Calculator(){
}
public T calculateSum(T a,T b){
return a; // I need to do something like a + b
}
}
I need to add the T object, I'm restricting the T to be only numeric types. How can I do this?
Thanks
Generic type arguments must be reference types, which excludes arithmetic types. You can give a boxed type such as Integer as the type argument, but that will not let you do arithmetic because auto-unboxing only works for particular, specific boxed types. Even if you restricted the type parameter to be a descendant of Number, there would be no way the compiler could be sure that the actual type argument was not some user-defined subclass of Number that did not have any auto-unboxing behavior.
More technically, generic types will not let you do anything that you wouldn't be able to achieve by inserting downcasts (and nothing else) in non-generic code. Here, it looks like you want to have a different kind of addition (integer or floating-point) depending on which type the argument is. And there is no way to achieve that solely by inserting casts; you'd have to insert some explicit condition that tested if the values happen to be Integer, then Long, then Float, et cetera. Since this is more complex than a downcast here or there, generics cannot, in principle, to this for you.
This is different from C++ templates, where each instantiation of the template generates (in principle, at least) a separate implementation in the compiler.
What you can do is make Calculator<T> an abstract class or an interface. Then make concrete subtypes such as
public class IntCalculator extends Calculator<Integer> {
public Integer calculateSum(Integer a, Integer b) {
return a+b;
}
}
public class DoubleCalculator extends Calculator<Double> {
public Double calculateSum(Double a, Double b) {
return a+b;
}
}
and so forth.
Methods (as well as classes) can have type parameters.
public class Calculator {
public Calculator(){
}
public <T extends Number > T calculateSum(T a,T b){
return a; // I need to do something like a + b
} }
Generics are not needed for this exercise.
public class Calculator {
public Calculator(){
}
public int calculateSum(int a,int b){
return a + b ;
}
public long calculateSum(long a,long b){
return a + b ;
}
.... you fill in the rest ...
}
In your declaration you need to make sure that T is always a sub-type of Number.
Instead of
Calculator<T>
try
Calculator<T extends Number>
then look in java.lang.Number and you should find a way to get a value that works with +.

Validate reflected method return type and parms in Java

I have a generic Callback object which provides a (primitive) callback capability for Java, in the absence of closures. The Callback object contains a Method, and returns the parameter and return types for the method via a couple of accessor methods that just delegate to the equivalent methods in Method.
I am trying to validate that a Callback I have been supplied points to a valid method. I need the return type assignment compatible with Number and all parameters to be assignment compatible with Double. My validating method looks like this:
static public void checkFunctionSpec(Callback cbk) {
Class[] prms=cbk.getParmTypes();
Class ret =cbk.getReturnType();
if(!Number.class.isAssignableFrom(ret)) {
throw new IllegalArgumentException(
"A function callback must return a Number type " +
"(any Number object or numeric primitive) - function '" +
cbk + "' is not permitted");
}
for(Class prm: prms) {
if(!Double.class.isAssignableFrom(prm)) {
throw new IllegalArgumentException(
"A function callback must take parameters of " +
"assignment compatible with double " +
"(a Double or Float object or a double or float primitive) " +
"- function '" + cbk + "' is not permitted");
}
}
}
The problem I encounter is that the when I try this with, e.g. Math.abs(), it's throwing an exception for the return type as follows:
java.lang.IllegalArgumentException:
A function callback must return a Number type (any Number object or numeric primitive)
- function 'public static double java.lang.Math.abs(double)' is not permitted
This was surprising to me because I expected primitives to simply work because (a) they are reflected using their wrapper classes, and (b) the Double.TYPE is declared to be of type Class<Double>.
Does anyone know how I can achieve this without modifying my checks to be:
if(!Number.class.isAssignableFrom(ret)
&& ret!=Double.TYPE
&& ret!=Float.TYPE
&& ret!=...) {
Clarification
When you invoke the method double abs(double) using Method.invoke(), you pass in a Object[]{Double} and get back a Double. However, my validation appears to be failing because Double.TYPE is not assignable to a Double. Since I require all these callbacks to return some sort of number, which will be returned by invoke() as a Number, I am trying to validate that the supplied method returns either Number or a numeric primitive.
Validation of the parms is likewise.
In other words, when using reflection the parm and return types Double and double are identical and I would like to validate them easily as such.
EDIT: To further clarify: I want to validate that a Method will, when invoke() is called return an Object of type Number (from which I can call obj.doubleValue() to get the double I want).
Looking more closely at the documentation for Class.isAssignableFrom(), it specifically states that the types for a primitive do not match any class except themselves. So I will need to specifically check for == equality to Byte.TYPE, Double.TYPE, Float.TYPE, Integer.TYPE, Long.TYPE, and Short.TYPE for the return type.
Why not have the compiler do it?
public interface F<A, B> {
public B $(A a);
}
Then you can pass an F<Double, Double> to a method that expects an F<? extends Number, ? extends Number>.
EDIT:
You say you want to provide a single class for the type of a function with any number of arguments. This can be done with the Java type system. Conceptually every function has only one argument. A function with two arguments is equivalent to a function that returns another function. So here's a variable whose value is a function that takes two doubles:
F<Double, F<Double, Double>> f;
Here's a method that passes two doubles to a given function:
public Double operate(F<Double, F<Double, Double>> f, double a, double b) {
return f.$(a).$(b);
}
Or, consider a type L<A extends L> with two subclasses C<E, T extends L<T>> representing a "cons", and a terminator type N:
public abstract class L<A extends L<A>> {
private L() {}
private static final N nil = new N();
public static N nil() {
return nil;
}
public static final class N extends L<N> {
private N() {}
public <E> C<E, N> cons(final E e) {
return new C<E, L>(e, this);
}
}
public static final class C<E, L extends L<L>> extends L<C<E, L>> {
private E e;
private L l;
private C(final E e, final L l) {
this.e = e;
this.l = l;
}
public E head() {
return e;
}
public L tail() {
return l;
}
public <E> C<E, C<E, L>> cons(final E e) {
return new C<E, C<E, L>>(e, this);
}
}
}
In such a case, you can implement a function type thusly:
public interface F<A extends L<A>, B> {
public B $(A args);
}
The following method expects a function with two Double arguments (and returns a Double), along with two doubles to apply it to:
public Double operate(F<C<Double, C<Double, N>>, Double> f, double a, double b) {
return f.$(N.nil().cons(b).cons(a));
}
The implementation of the F interface would have to get the arguments from the list using head and tail. So in effect, you're implementing LISP in Java. :)
Having said that, check out Functional Java, which is a library that has a lot of this stuff already. I'm sure there's also one out there that uses reflection so you don't have to write it yourself.
The parameter to Math.abs() is the double primitive. I'm not quite sure what you mean by a primitive being "assignment compatible" with an object (what the reflection API essentially means is "can be a cast of"). But if you mean "can pass into a Double constructor", then that's essentially a primitive double (or a string)!! Perhaps you need to clarify a bit more what you need to do?

Categories

Resources