Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Generic Type Number

I have read several pages on generic methods and have some sort of grasp on them, but I still don't understand them. So say I have a method to multiply two numbers and return the product:

public double multiply(SomeNumberVariableType x, SomeNumberVariableType y){
    return x * y;
}

How can I use bounded generics to have only a number type permitted as parameters?

like image 372
Dando18 Avatar asked May 16 '26 18:05

Dando18


2 Answers

Maybe this is your intention:

public static <N extends Number> double multiply(N x, N y){
    return x.doubleValue() * y.doubleValue();
}

Although I must also say that the generic use of Number instead of concrete immutable value types like java primitive double is probably not so healthy because in the example above the arguments could even be of different types, for example Integer and Double.

Attention:

I confirm, the arguments can be of different types as given signature above. So the answer of Bohemian is wrong. I have tested it just now (but knew it already before). The compiler only guarantees that both arguments are of type Number, nothing else.

In order to assert the same argument types the compiler needs self-referencing generics. This feature is not fulfilled by Number-class (that is <N extends Number<N>> is unfortunately not possible). That is why I consider the whole Number approach as not really healthy. Here a test code which everyone can execute:

Integer x = Integer.valueOf(10);
Double y = new Double(2.5);
System.out.println(multiply(x, y));
// Output: 25.0
like image 135
Meno Hochschild Avatar answered May 18 '26 06:05

Meno Hochschild


In general, Java generics are not appropriate for math.

In Java:

  • Generics are object only.
  • There are no mathematical operators for objects.

It looks like you can perform math on objects because you can do something like this:

Integer a = 1;
Integer b = 2;
Integer c = a + b;

But that is only due to autoboxing. What actually happens is the compiler replaces that code with this:

Integer a = new Integer(1);
Integer b = new Integer(3);
Integer c = Integer.valueOf(a.intValue() + b.intValue());

With generics you can specify a bound so that your type must be Number or a subtype of it:

static <N extends Number> N multiply(N n1, N n2) {
    return n1 * n2; // but you cannot do this because the type is not known
                    // so the compiler cannot do autoboxing
}

If a supertype is known, you can call methods on them so you can do this as has been pointed out:

static <N extends Number> double multiply(N n1, N n2) {
    return n1.doubleValue() * n2.doubleValue();
}

But that is no different than the following:

static double multiply(double n1, double n2) {
    return n1 * n2;
}

Except that the generic version can, for example, take BigDecimal as an argument which will of course not provide a reliable result (see BigDecimal#doubleValue). (Neither will Long for that matter.)

If you were really determined you could program your own number classes and use polymorphism. Otherwise use overloads or (best of all) stick to one type.

like image 25
Radiodef Avatar answered May 18 '26 08:05

Radiodef



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!