I'm having a strange behaviour with Generics I'm using Java8.
Here is a small sample code to demonstrate the problem Following code works fine without any issues with type inference. where, SpecificError is a subtype of GenericError.
public GenericType<AbstractError> method{
Optional<SpecificError> error = Optional.of(new SpecificError());
if (error.isPresent()) {
return GenericType.error(error.get());
} else {
// return something else
}
}
I have lot of this places in the code, where I had to do this if/else checks with optional, I decided to make a new function which receives the Optional, checks for presence and returns the Generic type object New function code:
public static <R extends AbstractError> GenericType<R> shortcut(Optional<R> error) {
if (error.isPresent()) {
return GenericType.error(error.get());
} else {
// something else
}
}
This is new code calling the above function:
public GenericType<AbstractError> method{
Optional<SpecificError> error = Optional.of(new SpecificError());
return GenericType.shortcut(error);
}
And strangely this does not work and breaks the following compilation error:
[ERROR] inferred: AbstractError
[ERROR] equality constraints(s): AbstractError, SpecificError
I just do not understand, why this won't work. The only thing, I have done is to make a small function which the job of doing isPresent check on Optional, everything else is the same. Why can't Java see that SpecificError is subtype of AbstractError
From the method method()
, you are calling GenericType.shortcut(error)
, where error
is of the type Optional<SpecificError>
. shortcut
demands a type argument R
, which you are trying to fulfill with R = SpecificError
. So you are trying to return a GenericType<SpecificError>
, but your method signature declares that it returns a GenericType<AbstractError>
.
A GenericType<SpecificError>
is not a GenericType<AbstractError>
, because generics are invariant .
You could fix this by replacing
Optional<SpecificError> error = Optional.of(new SpecificError());
with
Optional<AbstractError> error = Optional.of(new SpecificError());
As you declare the GenericType as <R extends AbstractError>
at shortcut()
It is now forced to return a subtype . That is why the compiler is creating issues.
The concept witnessed here is Type Equality Constraint , covered under Java Generics
Thing should get going if you change the method signature to
public static <R> GenericType<R> shortcut(Optional<R> error) { // remove extends AbstractError
public GenericType<AbstractError> method{
Optional<SpecificError> error = Optional.of(new SpecificError());
return GenericType.shortcut(error);
}
public static <R extends AbstractError> GenericType<R> shortcut(Optional<R> error) {
shortcut
needs an Optional
parameter whose type parameter matches the return type.
But yours doesn't: SpecificError
isn't the same as AbstractError
.
All you need is for error
to be R
or a subclass, so add an upper bound to the parameter type:
Optional<? extends R> error
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.