简体   繁体   中英

how can i determine the ACTUAL return type of a specific subclass of a generic superclass?

i do know that what i am trying to do it isn't really possible with pure java - it is only possible if i look at the debug info. i will not compile without debug anyway, because a buch of my spring mvc would stop working.

that said, i have the following situation:

one generic superclass:

package com.cinefms.apitester.springmvc.crawlers;

public class TestGenerics<T extends TestGenericsInterface> {

    public T get() {
        return null;
    }

    public T put(T t) {
        return null;
    }

}

and its subclass:

package com.cinefms.apitester.springmvc.crawlers;


public class TestGenericsSub extends TestGenerics<TestGenericsImpl> {

}

with the objects in there being really damn simple.

an interface:

package com.cinefms.apitester.springmvc.crawlers;

public interface TestGenericsInterface {

}

and it's implementation:

package com.cinefms.apitester.springmvc.crawlers;

public class TestGenericsImpl implements TestGenericsInterface {

}

eclipse is perfectly fine figuring out that of TestGenericsSub.get() should return an instance of TestGenericsImpl ... even if no source is available.

but how can i possible figure this out by myself at runtime?

if "m" is the Method "run", then

m.getGenericReturnType();

would return "T" (not helpful), while:

m.getReturnType();

gives me "TestGenericsInterface" (also not helpful). i have been looking at the "org.javaruntype" library ... but i can't seem to be able to figure it out.

could someone explain?

thanks!

Thanks to Java type erasure ( https://docs.oracle.com/javase/tutorial/java/generics/genTypes.html ), this is quite difficult. I suggest saving the class off as an attribute and then providing a getter if you absolutely must know the run-time type of T.

public class MyGenericClass<T> {

    private final Class<T> type;

    public MyGenericClass(Class<T> type) {
        this.type = type;
    }

    public Class<T> getMyType() {
        return this.type;
    }
}

Otherwise you can try something like:

(Class<T extends TestGenericsInterface>) ((TestGenerics) getClass().getGenericSuperclass()).getActualTypeArguments()[0];

I would prefer the former solution to the latter in code.

You can achieve that with ClassMate :

TypeResolver typeResolver = new TypeResolver();
MemberResolver memberResolver = new MemberResolver(typeResolver);

ResolvedType resolvedType = typeResolver.resolve(TestGenericsSub.class);
ResolvedTypeWithMembers resolvedTypeWithMembers = memberResolver.resolve(resolvedType, null, null);
ResolvedMethod resolvedGetMethod = resolvedTypeWithMembers.getMemberMethods()[0];

System.out.println(resolvedGetMethod.getReturnType()); // TestGenericsImpl

TypeTools is another option:

Class<?> t = TypeResolver.resolveRawArgument(TestGenerics.class, TestGenericsSub.class);

The result is as expected:

assert t == TestGenericsImpl.class;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM