反射-试图获取类字段的引用,以将其作为参数传递给函数



我正在尝试打印对象的公共属性,这些属性可以是基元,也可以是对象。通过使用Reflection,我设法打印方法(getMethods(((和基元字段(getDeclaredFields(((-线程中的异常";主";java.lang.IollegalArgumentException:无法将B字段A.b1设置为A

我的问题在


else {
Object o = f.get(this);
printProperties(o);

我如何将B类的引用发送到printProperties,以便进入B类并打印所有属性等?

示例-

public class A {
public String s1;
public int 1;
public B b1;
}
public class B {
public String s2;
public int 2;
public C c1;
}
public void printProperties(Object reflectObject) throws IllegalAccessException {
Class reflectClass = (Class) reflectObject;
String className = reflectClass.getName();
System.out.println(className);
Method [] classMethod = reflectClass.getMethods();
for(Method m :classMethod){
System.out.println("Name "+m.getName());
System.out.println("Return "+m.getReturnType());
}
System.out.println("Fields");
Field[] fields = reflectClass.getDeclaredFields();
for (Field f : fields){
if(f.getType().isPrimitive()||f.getType().isAssignableFrom(String.class)){
System.out.println("Field "+f.getName());
}
else {
Object o = f.get(this);
printProperties(o);
}

f.get(this)的问题是字段的声明类与this的类型不兼容。由于您是递归遍历字段,因此应该使用字段的值。下一行printProperties(o);表明您已经想到了这样一种方法。但这与方法的第一行Class reflectClass = (Class) reflectObject;相矛盾。字段的值不是Class对象。但是,第一次调用并没有立即以ClassCastException失败,而是到达了get(this)点,这表明该方法的初始调用方确实传递了Class对象,而不是实际的实例。

可以只使用声明的类型,而不使用运行时对象。如果您采用此路线,则应该保持一致,并将参数声明为Class:

public void printProperties(Class<?> reflectClass) throws IllegalAccessException {
String className = reflectClass.getName();
System.out.println(className);
for(Method m: reflectClass.getMethods()) {
System.out.println("Name " + m.getName());
System.out.println("Return " + m.getReturnType());
}
System.out.println("Fields");
for(Field f: reflectClass.getDeclaredFields()) {
System.out.println("Field " + f.getName());
Class<?> fieldType = f.getType();
if(!fieldType.isPrimitive() && fieldType != String.class) {
printProperties(fieldType);
}
}
}

然后,您可以用printProperties(getClass());printProperties(someObject.getClass());调用它,也可以直接指定类型,例如printProperties(A.class);

另一种方法是使用实际值及其类。在这种情况下,您必须修复调用者,以便传递对象,如printProperties(this);printProperties(someObject);。如果您传递了一个Class,而预期是Object,编译器不会发出警告。在这种情况下,您将检查类java.lang.Class

public void printProperties(Object reflectObject) throws IllegalAccessException {
Class<?> reflectClass = reflectObject.getClass();
String className = reflectClass.getName();
System.out.println(className);
for(Method m :reflectClass.getMethods()) {
System.out.println("Name " + m.getName());
System.out.println("Return " + m.getReturnType());
}
System.out.println("Fields");
for(Field f : reflectClass.getDeclaredFields()) {
System.out.println("Field " + f.getName());
Class<?> fieldType = f.getType();
if(!fieldType.isPrimitive() && fieldType != String.class) {
Object fieldValue = f.get(reflectObject);
if(fieldValue != null) printProperties(fieldValue);
}
}
}

这使用实际值的类型。因此,当字段引用子类型的对象时,将检查该子类型。另一方面,这种方法不能检测null。您可以将这两种方法结合起来,在字段的值为null时使用字段的声明类型。这是留给读者的练习。当您同时使用这两种方法时,建议为它们指定不同的名称,以最大限度地减少将ClassObject混淆的可能性。

相关内容

  • 没有找到相关文章

最新更新