Java Generic Type Number

混江龙づ霸主 提交于 2019-12-11 07:59:45

问题


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?


回答1:


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



回答2:


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.




回答3:


You can specify a bound to your type by coding <T extends Number>:

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

Which restricts the Number types to being the same type, eg an Integer and an Integer, but not an Integer and a Long.

but you don't need generics at all:

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

Which allows any two Numbers, eg an Integer and a Long.



来源:https://stackoverflow.com/questions/20819824/java-generic-type-number

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!