我有一个名为“ Test”的类,该类将传递给Test.class
类型的方法,该方法将为Class<T> clazz
。
我需要从该clazz变量调用Test类的toString()方法。我们可以使用反射来做到这一点而无需类型转换来测试吗?
答案 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
如您所见,无论是通过标准方式还是通过泛型甚至是更差的反射,都将导致相同的逻辑。
我希望这能启发您(和其他人);)