Leonardo Raele
Leonardo Raele

Reputation: 2824

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

I have a Generic method that should work similarly to recursion, but calling different instances of the method for each calling.

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 the line with a comment does not compile, giving the following error:

The method doSomething(Class, M) in the type MainTest is not applicable for the arguments (Class, capture#3-of ? extends A)

I don't quite understand why the compiler does not compile if it can call doSomething with M = "? extends A".

Why doesn't it compile?

Upvotes: 3

Views: 185

Answers (3)

SylvainL
SylvainL

Reputation: 3938

When you are asking the compiler to perform a cast, the exact type to perform the cast must be known. It is not sufficient to tell the compiler that you don't know about the exact type excerpt that it's a subclass of A.

Class tell the compiler that the type of the object is a subclass of A but it doesn't tell the compilator the exact type to be used for the casting.

Your problem is that you are trying to replace Polymorphism with Generic. As you are learning the hard way, Generic is not the new modern way of doing Polymorphism.

Upvotes: 1

Tom Hawtin - tackline
Tom Hawtin - tackline

Reputation: 147154

The language does not track wildcards like that (it seems). What you need to do is to capture that wildcard, which can be done with a method call with type inference.

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, whilst reflection has some uses, it's usually a sign of confusion.

Upvotes: 2

Aniket Lawande
Aniket Lawande

Reputation: 131

Ok here is a crude explanation

You've typed your method so that it will accept M which is a subtype of A

Now you are calling 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 bit more, I can help with a solution.

Upvotes: 4

Related Questions