Issue
I struggle with the following inner class "inheriting" the generic parameter T
from the outer class. The following lines are erroneous:
String string = "string";
new OuterClass<>()
.inner(string)
.call(s -> s.length()); // Cannot resolve method 'length' in 'Object'
Minimal and reproducible example of these classes:
public class OuterClass<T> {
public InnerClass<T> inner(T object) {
return new InnerClass<>(object);
}
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public static final class InnerClass<U> {
U object;
public final void call(Consumer<U> consumer) {
consumer.accept(object);
}
}
}
Why does this happen? How am I supposed to specify the generic parameter through the creation of the inner class?
Solution
Essentially, this is because inference of type in the <>
does not take into account the subsequent methods that you chain.
For example, this creates an ArrayList<Object>
:
new ArrayList<>().add("");
If I insert the word String
inside the <>
, IntelliJ will not complain that the word String
is redundant.
Similarly, this produces an error:
OuterClass<String>.InnerClass i = new OuterClass<>().inner(string);
Because the right hand side produces a OuterClass<Object>.Inner
, while the left hand side is a OuterClass<String>.InnerClass
.
To fix this, you need to specify the generic parameter:
new OuterClass<String>()
.inner(string)
.call(s -> s.length());
Regarding your edit, the edited inner
method still depends on the generic type of Outer
, which cannot be inferred correctly.
You can make the Inner
object created not depend on the generic type of Outer
by adding another generic parameter:
public <U> InnerClass<U> inner(U object) {
return new InnerClass<>(object);
}
Answered By - Sweeper
Answer Checked By - David Goodson (JavaFixing Volunteer)