I struggled to find a proper title for this question because the phenomenon I observed is very strange. Hence I skip explaining my problem literally and instead show you some (hopefully) self-describing code. Consider the following parameterized class:
public class GenericOptional<T> {
public GenericOptional(T someValue) {}
public T getValue() { return null; }
public Optional<String> getOptionalString() { return Optional.empty(); }
}
What I like to emphasize is that the return type Optional<String>
of the method getOptionalString()
does not depend on the type-parameter T
.
Now have a look at the following code, which gets compiled inside Eclipse Luna 4.4.2 using Java 8u45:
public static void main(String[] args) {
Object obj = new GenericOptional<>(Boolean.TRUE);
GenericOptional go = (GenericOptional) obj;
Optional os = go.getOptionalString();
}
The local variable os
has the type Optional
without the type-parameter String
! The Eclipse compiler has lost the information about the fixed type-parameter. Does anyone know why?
Now look at a second code example:
public static void main(String[] args) {
Object obj = new GenericOptional<>(Boolean.TRUE);
GenericOptional<?> go = (GenericOptional) obj;
Optional<String> os = go.getOptionalString();
}
By declaring the local variable go
as GenericOptional<?>
the return type of the method getOptionalString()
now is Optional<String>
as expected.
May anyone explain this behavior?
You are facing the behavior of raw types. When you are using a raw type, Generics are effectively turned off completely, regardless of whether there is a connection between the generic signature of the member and the type parameter of the class.
The reasoning behind this is that raw types are a feature for backward compatibility with pre-Generics code only. So either you have Generics or your don’t.
If the Generic method does not depend on the actual type parameter of the class, the problem is easy to fix:
GenericOptional<?> go = (GenericOptional<?>) obj;
Optional<String> os = go.getOptionalString();
Using <?>
implies “I don’t know the actual type parameter and I don’t care but I’m using Generic type checking”.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With