I've got an issue with a generic framework I'm writing. Can someone explain to me, why my code does not compile? I've tried to show it with this simple example. (UPDATED EXAMPLE)
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
public class TestGeneric {
public static void main(String... sss) throws Exception {
Dao dao = new Dao("Hello");
dao.extend();
System.out.println(dao.getHelloWorld());
}
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface TestAnnotation {
public Class<? extends AbstractCommand<? extends AbstractDao>>[] commands() default {};
}
abstract class AbstractDao {
public void extend() throws Exception {
for (Field field : this.getClass().getDeclaredFields()) {
if (field.isAnnotationPresent(TestAnnotation.class)) {
TestAnnotation annotation = field.getAnnotation(TestAnnotation.class);
for (Class<? extends AbstractCommand<? extends AbstractDao>> commandClass : annotation.commands()) {
AbstractCommand<? extends AbstractDao> command = commandClass.newInstance();
command.doSomething(this);
}
}
}
}
}
class Dao extends AbstractDao {
@TestAnnotation(commands = { Command.class })
private String hello;
private String world;
public Dao(String hello) {
this.hello = hello;
}
public String getHello() {
return this.hello;
}
public void setWorld(String world) {
this.world = world;
}
public String getHelloWorld() {
return this.hello + " " + this.world;
}
}
abstract class AbstractCommand<T extends AbstractDao> {
public abstract void doSomething(T t);
}
class Command extends AbstractCommand<Dao> {
@Override
public void doSomething(Dao t) {
if (t.getHello().equals("Hello")) {
t.setWorld("World");
}
}
}
As soon as I make following changes ...
abstract class AbstractCommand<T extends AbstractDao> {
public abstract void print(AbstractDao t);
}
class Command extends AbstractCommand<Dao> {
@Override
public void doSomething(AbstractDao t) {
Dao dao = (Dao) t;
if (dao.getHello().equals("Hello")) {
dao.setWorld("World");
}
}
}
... everything works fine, but then I have to cast AbstractDao all the time.
As far as I can say, everything should be save, but I keep getting this error.
The method print(capture#3-of ? extends AbstractDao) in the type AbstractCommand is not applicable for the arguments (Dao)
But Dao extends AbstractDao, so where exactly is the problem?
I already found this question generics error: not applicable for the arguments but I'm not sure whether or not it is the same problem I have.
My guess is that it has something to do with 'Because the Java compiler erases all type parameters in generic code, you cannot verify which parameterized type for a generic type is being used at runtime'
Does anyone have a solution for this problem?
Thanks!