Generic as method return type

2019-08-16 05:50发布

问题:

I have looked around on StackOverflow to find the answer for the problem I am facing. I came across many good answers but still it doesn't answer my question.

Get type of a generic parameter in Java with reflection

How to find the parameterized type of the return type through inspection?

Java generics: get class of generic method's return type

http://qussay.com/2013/09/28/handling-java-generic-types-with-reflection/

http://gafter.blogspot.com/search?q=super+type+token

So here is what I want to do. Using Reflection, I want to get all methods and its return type (non-generic). I have been using Introspector.getBeanInfo to do so. However I hit the limitation when I run into a method where return type is unknown.

public class Foo {

    public String name;

    public String getName() {
        return name;
    }

    public void setName(final String name) {
        this.name = name;
    }
}

public class Bar<T> {

    T object;

    public T getObject() {
        return object;
    }

    public void setObject(final T object) {
        this.object = object;
    }
}

@Test
    public void testFooBar() throws NoSuchMethodException, SecurityException, IllegalAccessException,
            IllegalArgumentException, InvocationTargetException {

        Foo foo = new Foo();
        Bar<Foo> bar = new Bar<Foo>();
        bar.setObject(foo);
        Method mRead = bar.getClass().getMethod("getObject", null);

        System.out.println(Foo.class);// Foo
        System.out.println(foo.getClass());// Foo
        System.out.println(Bar.class);// Bar
        System.out.println(bar.getClass());// Bar
        System.out.println(mRead.getReturnType()); // java.lang.Object
        System.out.println(mRead.getGenericReturnType());// T
        System.out.println(mRead.getGenericReturnType());// T
        System.out.println(mRead.invoke(bar, null).getClass());// Foo
    }

How do I know if the method return type T is generic or not? I don't have a luxury to have an object at runtime. I am experimenting with Google TypeToken or use an abstract class to get type information. I want to associate T to Foo for the getObject method for Bar<Foo> object.

Some have argued that java doesn't preserve the generic information. In that case why first casting works and second casting doesn't.

Object fooObject = new Foo();
bar.setObject((Foo) fooObject); //This works
Object object = 12;
bar.setObject((Foo) object); //This throws casting error

Any help is appreciated.

回答1:

Bar<Foo> bar = new Bar<Foo>();
Method mRead = bar.getClass().getMethod( "getObject", null );
TypeToken<Bar<Foo>> tt = new TypeToken<Test.Bar<Foo>>() {};
Invokable<Bar<Foo>, Object> inv = tt.method( mRead );
System.out.println( inv.getReturnType() ); // Test$Foo

Maybe this is what you are searching for. TypeToken and Invokable are from Google Guava.

€: Fixed the code with respect to the comment of @PaulBellora