8

Following code is throwing compile time exception

Type mismatch: cannot convert from Integer to K

What I understand is K should handle any value that extends Number.

public <K extends Number> K getValue(){
    Integer a = new Integer(1);
    return a;//Type mismatch: cannot convert from Integer to K
}

(Note: This is just a test code to put my question without giving irrelevant details of my actual scenario.)

ManishKr
  • 211
  • 2
  • 9
  • 2
    The compiler is right. For example, at some point when you invoke this method, you will define the actual type of `K`, for example `K` could be defined as `Double`. In that case, K would not be an Integer and your code would be wrong. You're misunderstanding the meaning of "extends" here. In other words, you don't have any guarantee that because `K` extends Number, that K will be an Integer, it could a Double, or a Float or any other orthogonal type that extends number. – Edwin Dalorzo Nov 25 '16 at 17:21
  • what if it would have been ``. It will still give me same warning message. – ManishKr Nov 25 '16 at 17:32
  • [This](http://stackoverflow.com/questions/2723397/what-is-pecs-producer-extends-consumer-super) will maybe help understand things better. – biziclop Nov 25 '16 at 17:49
  • 1
    You bring an interesting point. The expectation would be that since `K` is a type that extends `Integer` that the compiler would know you can assign an `Integer` to `K` (i.e. `K k = new Integer(10)`. However that seems not to be the case. For all that matters, the compiler expects `K` to be bound to some type that extends Integer at some point and it will enforce that constraint, but `K` is not Integer, instead `K` is a type on its own and it seems the compiler makes no polymorphic inferences about it. I suppose a cast could be forced (i.e. `(K) new Integer(10)`. – Edwin Dalorzo Nov 25 '16 at 17:54
  • 3
    To put it another way: the type parameter `` does not mean "any type that extends `SomeType`", but rather "a single, specific, but yet unknown subtype of `SomeType`". From this it's also easy to see why it doesn't make sense to use this as purely a return type of a method. If you just want to say "this method can return any subtype of `Number`", you don't need type parameters at all: `public Number getNumber()` already does that. – biziclop Nov 25 '16 at 17:58

1 Answers1

10

The problem here is the fact that K is a type that extends Number but it is an unknown sub class of Number that is why the compiler raises this error because Integer is only one specific sub class of Number so it cannot match with any potential target types.

Let's say that you want to cast it explicitly to make it compile with

public <K extends Number> K getValue(){
    Integer a = new Integer(1);
    return (K) a;
}

Then if you call it expecting any sub class of Number except Integer you will get a ClassCastException, that is exactly what the compiler wants to avoid:

Double d = getValue(); <-- throws ClassCastException

As workaround you could define your method using Number as returned type as next:

public Number getValue() {
    return new Integer(1);
}
Nicolas Filotto
  • 43,537
  • 11
  • 94
  • 122