反射无法获得从泛型类型接口覆盖的方法的实际参数类型?

时间:2016-03-04 09:47:57

标签: java reflection

编辑:对不起,我在下面提供的示例并没有重现问题...我试图找到正确的方法来重现它。在此之前,您可能会忽略我的问题......

通常我们抓住这样一个方法的参数类型:

Class<?> clazz = method.getParameterTypes()[0]

我之前从未考虑过这个问题,但最近我碰到了一个问题,我在做这件事时总是class java.lang.Object。经过检查,我发现案件可以这样描述:

/** A parameterized interface */
public interface IService<T> {

    Result create(T obj);
}

/** An implementation */
public class CarService implements IService<Car> {

    public Result create(Car car) { ... }
}

然后,当我使用上面的方法获取参数car的类时,结果是class java.lang.Object

Method methods = CarService.class.getMethods();
for (Method method : methods) {
    Class<?>[] types = method.getParameterTypes();
    // when the loop meets "create" here ...
}

我想我完全忘记了关于类型擦除的一些非常基本的东西?但是现在我真的需要在这种情况下得到实际的参数类型,如果它可能......

1 个答案:

答案 0 :(得分:2)

是的,这是类型擦除令人讨厌。值得在这里查看字节码中的内容:

class Car {}
interface IService<T> {
    void create(T obj);
}

class CarService implements IService<Car> {
    public void create(Car car) {}
}

然后:

$ javac Test.java # Contains all the above...
$ javap -c CarService

Compiled from "Test.java"
class CarService implements IService<Car> {
  CarService();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public void create(Car);
    Code:
       0: return

  public void create(java.lang.Object);
    Code:
       0: aload_0
       1: aload_1
       2: checkcast     #2                  // class Car
       5: invokevirtual #3                  // Method create:(LCar;)V
       8: return
}

当你使用反射时,这些显示:

public class Test {
    public static void main(String[] args) {
        Method[] methods = CarService.class.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method.getName());
            for (Class<?> type : method.getParameterTypes()) {
                System.out.printf("- %s%n", type.getName());
            }
        }
    }
}

输出:

create
- Car
create
- java.lang.Object

你如何使用它将取决于你正在尝试实现的目标,但希望知道字节码中有多种方法将有助于...