2013-05-29 86 views
3

我有一个类如下。使用反射获取使用超类的子类字段?

public class Emp{ 

private String name; 
private String age; 

//setters and getters 

} 

下面还有一个类。

public class Student extends Emp{ 
private int marks; 
//setters and getters 
} 

是否有无论如何获得使用java反射的超类的子类的字段? 我需要使用Emp实例来获取学生字段。

我们可以得到超类字段如下:

subClass.getClass().getSuperclass().getDeclaredFields(); 

同样可以得到我使用超类的子类字段?

可能吗?

谢谢!

+1

不,这是不可能得到关于父类的子类的信息,因为父类(正确地)不知道哪些类扩展它。 – nitegazer2003

回答

2

在理论上存在通过检索all loaded classes和他们是从Emp导出并包含现场检查一个非常复杂和昂贵的方式。如果所需的班级尚未加载,这可能也无济于事。

3

我可能误解了你的问题。你想做类似以下的事情吗?

Emp e = new Student(...); 
[do something with e] 
foo = e.marks; 

如果是的话,像这样做:

foo = ((Emp)e).marks; 

但是,如果你想要做的东西像下面这样:

Emp e = new Emp(...); 
[do something with e] 
e.marks = .... 

然后不,这是不可能的,我如果你怀疑你的Java对象模型的内部模型不完整或有缺陷。

+0

+1我同意这里可能会有一些混淆类如何工作。 *实例*是'Student',所以引用可以是向下的,或者不是,所以根本就没有'marks'字段。反思并不以任何方式进入。 –

1

不是直接的,你必须写一个辅助方法。

您将一个类和字段名称(以及可能的类型)作为参数,然后在给定的类中查找该字段。如果你无法找到它,那么你需要从课程的超类中重新开始。直到找到该字段为止,或者getSuperClass()返回null(意味着您已到达继承树的根目录)。

本示例演示如何在对象上调用查找并调用指定的方法。您可以轻松提取和调整字段的逻辑。

public static Object call(final Object instance, 
          final String methodName, 
          final Class<?>[] signature, 
          final Object[] args) { 
    try { 
     if (instance == null) 
      return null; 
     Class<?> instanceClass = instance.getClass(); 
     while (instanceClass != null) { 
      try { 
       final Method method = instanceClass.getDeclaredMethod(methodName, signature); 
       if (!method.isAccessible()) 
        method.setAccessible(true); 
       return method.invoke(instance, args); 
      } catch (final NoSuchMethodException e) { 
       // ignore 
      } 
      instanceClass = instanceClass.getSuperclass(); 
     } 
    } catch (final Throwable e) { 
     return null; 
    } 
    return null; 
} 
1

是你想要的吗?但要小心使用field.setAccesible。

父类:

public class ParentClass { 
     private String parentField = "parentFieldValue"; 
     public void printFields() throws IllegalAccessException { 
      Field[] fields = getClass().getDeclaredFields(); 
      for (Field field : fields) { 
        field.setAccessible(true); 
        Object fieldValue = field.get(this); 
        if (fieldValue instanceof String) { 
          String stringValue = (String) fieldValue; 
          System.out.println(stringValue); 
        } 
      } 
     } 
} 

子类:

public class ChildClass extends ParentClass {  
     private String childField = "childFieldValue"; 
} 

用法:

public class Main { 
     public static void main(String[] args) throws IllegalAccessException { 
      ParentClass pc = new ParentClass(); 
      ChildClass cc = new ChildClass(); 
      pc.printFields(); 
      cc.printFields(); 
     } 
} 
0

这是最后的解决方案!

@NonNull 
    public static List<Class<?>> getSubClasses() { 
     StackTraceElement[] trace = Thread.currentThread().getStackTrace(); 
     String method = trace[3].getMethodName(); 
     if (!"<init>".equals(method)) { 
      throw new IllegalStateException("You can only call this method from constructor!"); 
     } 
     List<Class<?>> subClasses = new ArrayList<>(); 
     for (int i = 4; i < trace.length; i++) { 
      method = trace[i].getMethodName(); 
      if ("<init>".equals(method)) { 
       try { 
        subClasses.add(Class.forName(trace[i].getClassName())); 
       } catch (ClassNotFoundException e) { 
        throw new RuntimeException(e); 
       } 
      } else { 
       break; 
      } 
     } 
     return subClasses; 
    } 

这是一些用法示例:

class a { 
public a(){ 
print(getSubClasses()); 
} 
} 
class b extends a{ 
} 
class c extends b{ 
} 

,其结果是

new a() -> [] 
new b() -> [b.class] 
new c() -> [b.class, c.class]