开发者

Java and generics. Isn't 0 a Number?

开发者 https://www.devze.com 2023-03-23 00:35 出处:网络
What is that I\'m missing about this snippet of code? public class开发者_开发百科 Zero<N extends Number> {

What is that I'm missing about this snippet of code?

public class开发者_开发百科 Zero<N extends Number> {
  public N zero() {
    return new Integer(0);
  }
}

It says:

Type mismatch: cannot convert from Integer to N

Thanks!

Update I've changed the snippet to use an integer. Same thing happens. And it happens even when creating an anonymous subclass of Number. Could it be Eclipse that is faulty about this?


While an Integer is a Number, an Integer might not be compatible to N which can be any subclass of Number.


Integer is not guaranteed to be a superclass of N, so you can't just set an Integer value to an object of type N.

Think about it this way: If someone instantiates Zero<N> as Zero<Double>, the class effectively becomes:

public class Zero {
  public Double zero() {
    return new Integer(0);
  }
}

which is obviously not valid.

Furthermore, you can't do return 0 either, because in the same manner, there is no way for the compiler to know how to convert it into N. (The compiler can only autobox types it knows about, but by using generics you widened the available types to also include custom implementations of Number.)


The problem with your code is that Java needs to be able to confirm that the return type of the function needs to be convertible to N extends Number for any N. So, in particular, if I were to instantiate the class with a Double, as in

Zero<Double> z = new Zero<Double>();
z.zero();

You'd run into trouble, because zero says that it returns a Double but it actually returns an Integer. The type error indicates that the compiler is concerned that something like this will happen.

To the best of my knowledge, there is no good way to do this in Java because generics are implemented via erasure; it can't know what the type of the argument is.


0 is an int, but since your method returns an object, it will be autoboxed to an Integer. The problem is that returning an Integer where any subclass of Number is allowed is not allowed by the compiler. That's simply because you can instantiate your class as

new Zero<Double>()

and in this case, returning Integer would not be compatible with the expected return type: Double.


When 'N' extends 'Number', 'N' becomes a specialization of 'Number' and you cannot assign an instance of a base class to a reference variable of it's specialization (upcast issue). This holds good while returning as well. A base class instance cannot be returned using the specialization type.

0

精彩评论

暂无评论...
验证码 换一张
取 消