What is causing this compilation error with java Generics and reflection?

I have a generic method that should work similarly to recursion, but calls different instances of the method for each call.

public <M extends A> void doSomething(Class<M> mClass, M mObject)
{
    // ... Do something with mObject.

    A object = getObject();
    Class<? extends A> objectClass = object.getClass();

    doSomething(objectClass, objectClass.cast(object)); // Does not compile.
}

private A getObject() {...}

      

The problem is that the comment line doesn't compile, resulting in the following error:

The doSomething (class, M) method in type MainTest is not valid for arguments (Class, capture # 3-of? Extends A)

I don't quite understand why the compiler won't compile if it can call doSomething

with M = "? Extends A".

Why won't it compile?

+3


source to share


3 answers


The language doesn't keep track of such wildcards (it seems). What you need to do is capture this wildcard, which can be accomplished by calling a method with an output type.

public <M extends A> void doSomething(Class<M> mClass, M mObject) {
    // ... Do something with mObject.

    A object = getObject();
    Class<? extends A> objectClass = object.getClass();
    privateSomething(objectClass, object);
}
private <T extends A> void privateSomething(Class<T> objectClass, A object) {
    doSomething(objectClass, objectClass.cast(object)); // Should compile.
}

      



As always, while reflection has some uses, it is usually a sign of confusion.

+2


source


Ok, this is a rough explanation

You typed your method to accept M which is a subtype of A

Now you call your method using "objectClass", which is a subtype of A , but not necessarily a subtype of M.



Hence the compiler is complaining ...

If you can explain what you are trying to do a little more, I can help with a solution.

+4


source


When you ask the compiler to cast, the exact type of role execution must be known. It is not enough to tell the compiler that you are not aware of the exact type statement that it is a subclass of A.

The class tells the compiler that the object's type is a subclass of A, but it does not tell the compiler the exact type to use for casting.

Your problem is that you are trying to replace Polymorphism with Generic. Since you're learning the hard way, Generic is not a new modern way of doing polymorphism.

+1


source







All Articles