问题
I wonder why the following generic definition does not produce a compiler warning:
class MyClass<T extends List> { }
and how the above definition is different to
class MyClass<T extends List<?>> { }
Whenever you read about generics, you read about how raw types should be avoided and consequently, whenever you handle generic types, you get a compiler warning. The raw type inside of the first definition does however not create such a warning.
Secondly, I wonder how the exact subtyping definition between raw types and generic types are. According to this summary, raw types are kind of an "opt-out" of type checking such that type checking is simply inactive whenever a raw type is involved. Is this assumption correct? And how does this effect the above "raw" generic definitions?
Thank you for your help!
UPDATE: I understand what you are saying. However, this is not what I am confused about. Look at this scenario:
class MyClass<T extends MyClass<T>> {}
public void callWildcard1(MyClass<?> node) {
callBound1(node);
}
public <T extends MyClass<T>> void callBound1(T node) {
// Do something
}
public void callWildcard2(MyClass<?> node) {
callBound2(node);
}
public <T extends MyClass> void callBound2(T node) {
// Do something
}
The first call from callWildcard1
to callBound1
is not allowed because of the generic constraint. The second is however allowed. How can I perform the first call without "inner raw types"? I don't see why the compiler would forbid the first. Shouln't any parameter valid wildcard parameter imply ? extends MyClass<?>
?
UPDATE 2: I found out by trial and error, that I can solve the problem by defining:
public <T extends MyClass<? extends T> void callBound2(T node) {
// Do something
}
even though I do not quite understand why. But there is even more confusion, when looking at this example: (this is a very simple version of what I am actually trying to do.)
public void call() {
genericCall1(new MyFilter<MyClass<?>>(), MyClass.class);
genericCall2(new MyFilter<MyClass<?>>(), MyClass.class);
}
public <T extends MyClass<? extends T>> void genericCall1(MyFilter<T> filter, Class<? extends T> filterBoundary) {
// Do something.
}
public <T extends MyClass<? extends T>, U extends T> void genericCall2(MyFilter<T> filter, Class<? extends U> filterBoundary) {
// Do something.
}
class MyClass<T extends MyClass<T>> { }
class MyFilter<T extends MyClass<? extends T>> { }
Why is genericCall1
prohibited and genericCall2
is not? Again, I found the solution by an academic guess instead of true understanding. Sometimes, when working with Java and its generics I want to cry...
回答1:
The difference is that when you use class MyClass<T extends List> { }
inside MyClass
you lose type safety.
for example:
class A <T extends List<?>>{
void someFunc(T t) {
t.add(new Object());//compilation error
}
}
class B <T extends List>{
void someFunc(T t) {
//compiles fine
t.add(new Object());
t.add("string");
t.add(new Integer(3));
}
}
来源:https://stackoverflow.com/questions/17061292/raw-types-inside-of-generic-definition