Reputation: 873
Below I have a generic OuterClass, an InnerClass that use OuterClass generics and non-generic InnerInterface.
public class OuterClass<E> {
public class InnerClass {
public E someMethod() {
return null;
}
}
public interface InnerInterface{
public void onEvent(OuterClass.InnerClass innerClass);
}
}
In the main method below, I use two instance of OuterClass, o1 parameterized with , and o2 with . My annonymous inner class myListener tries to use the generic type of the outer class (E). The code as it is below does not compile (Integer i = innerClass.someMethod() - Type mismatch: cannot convert from Object to Integer).
public class Test {
public static void main(String[] args) {
OuterClass<Integer> o1 = new OuterClass<Integer>();
OuterClass<String> o2 = new OuterClass<String>();
OuterClass.InnerInterface innerInterface = new OuterClass.InnerInterface() {
@Override
public void onEvent(InnerClass innerClass) {
Integer i = innerClass.someMethod();
}
};
}
}
I would like to express that myListener is for o1, and should use E = Integer, without repeating it (without repeating , I already say it when declaring o1). Is that possible?
Many thanks! Faton.
Upvotes: 10
Views: 16588
Reputation: 147154
As always, non-private
nested types don't help keeping things simple. Push the boat out and create some new files, even if your IDe works against you.
Anyway, static members of a class do not share the generic parameters of the outer class. This is important for the behaviour of fields, and allows more flexibility on static nested types (such as InnerInterface
) even if you don't want it. So, in your case, you need to give your (static) nested interface a generic parameter. For $deity's sake, use a different identifier!
public class OuterClass<E> {
public class InnerClass {
public E someMethod() {
return null;
}
}
public interface InnerInterface<T> {
void onEvent(OuterClass<T>.InnerClass innerClass);
}
}
public class Test {
public static void main(String[] args) {
OuterClass<Integer> o1 = new OuterClass<Integer>();
OuterClass<String> o2 = new OuterClass<String>();
OuterClass.InnerInterface<Integer> innerInterface =
new OuterClass.InnerInterface<Integer>()
{
@Override
public void onEvent(OuterClass<Integer>.InnerClass innerClass) {
Integer i = innerClass.someMethod();
}
};
}
}
(I've also qualified InnerClass
where necessary.)
Edit: It's probably worth just looking at the original anonymous inner class in isolation from the rest of the use:
public interface InnerInterface{
public void onEvent(OuterClass.InnerClass innerClass);
}
OuterClass.InnerInterface innerInterface = new OuterClass.InnerInterface() {
@Override
public void onEvent(InnerClass innerClass) {
Integer i = innerClass.someMethod();
}
};
Integer
only appears once, in a place where it clearly cannot be inferred to be correct.
Upvotes: 1
Reputation: 6875
An inner interface or enum is implicitely static, and static members are not parameterized with the type parameters of the outer class. So InnerInterface
should look like this:
public interface InnerInterface<E> {
void onEvent(OuterClass<E>.InnerClass innerClass);
}
Note that the E
parameter of InnerInterface
is not the same as the E
parameter of OuterClass
.
Upvotes: 16