从.class(Class <!-?->)调用Object的toString()方法

时间:2019-03-19 11:15:46

标签: java android generics reflection

我有一个名为“ Test”的类,该类将传递给Test.class类型的方法,该方法将为Class<T> clazz

我需要从该clazz变量调用Test类的toString()方法。我们可以使用反射来做到这一点而无需类型转换来测试吗?

2 个答案:

答案 0 :(得分:1)

首先从clazz变量创建对象,然后调用该对象的toString()方法。

clazz.newInstance().toString();

如果您具有默认构造函数,则它也将起作用:

clazz.getConstructor().newInstance().toString();

已更新: 如果要制作常规测试功能,则必须实现这样的测试功能。

public void TestToString(Object obj,String expectedVal){
    assertEquals(obj.toString(),expectedVal);
  }

答案 1 :(得分:0)

无法在Class参数上调用方法。 这只是对类的描述,但是要调用方法,您将需要对类进行实例化。
您可以:
  -使用Reflection创建.class参数的实例以在
上调用方法
 -使用反射调用实例上的方法。

但是最重要的是,您 需要 一个实例。

还有一点评论(如Joachim Sauer所说):
toString()类中存在Object方法,并且所有内容都扩展了Object类,因此它始终可用。
不需要反射,泛型或强制转换。 您只需在类中重写此方法,就可以了。

一个小例子来演示调用toString()的不同方法:

public class Test {

    private String name = "unnamed";

    public Test() {}

    public Test(String name) {
        this.name = name;
    }

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

    public String toString() {
        return name;
    }

    public static <T> T doReflectionCreateToString(Class<T> clazz) {
        try {
            T newT = clazz.getConstructor(String.class).newInstance("Name 2");
            System.out.println("Created by reflection:    "+ newT);
            return newT;
        } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
                | NoSuchMethodException | SecurityException e) {
            e.printStackTrace();
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    public static <T, E> E doReflectionCall(T obj, String methodName, Object[] arguments, Class<E> returnClazz) {
        try {
            Class<?> clazz = obj.getClass();
            Method myMethod = clazz.getDeclaredMethod(methodName);
            return (E) myMethod.invoke(obj, arguments);
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static <T> void doGenericToString(T obj) {
        System.out.println("toString by Generic way:  "+ obj);
    }

    public static void main(String[] args) {
        Test t = new Test();
        t.setName("Name 1");

        System.out.println("toString by standard way: "+ t);

        doGenericToString(t);

        System.out.println("Called by reflection:     "+ doReflectionCall(t, "toString", new Object[]{}, String.class));

        Test newT = doReflectionCreateToString(Test.class);
        System.out.println("Returned by reflection:   "+ newT);
    }
}

哪个输出:

  

toString以标准方式:名称1
  以通用方式toString:名称1
  通过反射调用:名称1
  通过反射创建:名称2
  通过反射返回:名称2

如您所见,无论是通过标准方式还是通过泛型甚至是更差的反射,都将导致相同的逻辑。
我希望这能启发您(和其他人);)