Can someone tell my why this gives a compile error? I don't see why the cast to A in the second for-loop causes strings() to return a general List of Objects.
import java.util.ArrayList;
import java.util.List;
public class E {
public static void main(String[] args) {
for (String s : new D().strings()) {
System.out.println("s = " + s);
}
for (String s : ((A) new D()).strings()) {
System.out.println("s = " + s);
}
}
static class D extends A<C> {
}
static abstract class A<T extends B> {
List<String> strings() {
return new ArrayList<String>() {{
add("Foo");
add("Bar!");
}};
}
}
static class B {
}
static class C extends B {
}
}
Is this a Generics quirk?
Thanks, Kristian
Yes, we can define a parameterized constructor in an abstract class.
Abstract types cannot be used as parameter types, as function return types, or as the type of an explicit conversion (note this is checked at the point of definition and function call, since at the point of function declaration parameter and return type may be incomplete).
An abstract class can have one or multiple number of unimplemented methods. As an abstract class is not proper, or does not have ideally defined methods compared to a regular class, so abstract classes cannot be instantiated, that means we cannot create any direct objects of abstract classes.
Abstract base classes are useful for creating polymorphic programs. An abstract base class defines an interface without an implementation. Each abstract base class has one or more concrete derived classes. Concrete derived classes implement the interface defined by their abstract base class.
In the line:
for (String s : ((A) new D()).strings()) {
You are casting to the raw type A
, so you lose the type arguments information there. In Java, any use method or field on a raw type would also result in a raw type (even if all the parameterized information is available) -- well raw type or non-parameterized technically. So A.string()
is viewed as the raw type List
rather than List<String>
.
As the JSL specifies in Section 4.8:
The type of a constructor (§8.8), instance method (§8.8, §9.4), or non-static field (§8.3) M of a raw type C that is not inherited from its superclasses or superinterfaces is the erasure of its type in the generic declaration corresponding to C. The type of a static member of a raw type C is the same as its type in the generic declaration corresponding to C.
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