在抽象类中获取对私有final字段的引用

时间:2013-06-20 04:55:45

标签: java reflection field abstract

我引用了对象 A ,它是抽象的。此对象也是对象 B C D 的实例。

无论扩展类如何,我都需要在 A 中引用某个类型的私有最终字段。

我不知道字段的名称,只知道它的类型,它对抽象类中的所有其他字段都是唯一的。我无法更改列出的四个类中的任何一个的代码。使用getDeclaredFields()返回我当时扩展类中的字段。

如何获得对此字段的引用?

3 个答案:

答案 0 :(得分:2)

如果您没有直接上课,那么您可以按照以下方式进行操作 -

Field[] fields = obj.getClass().getSuperclass().getDeclaredFields();
for(Field field : fields) {
    if(field.getType() == String.class) { //assume the type is String

    }
}

但是如果你有权访问该课程,那么它将是

Field[] fields = B.class.getSuperclass().getDeclaredFields();

甚至

Field[] fields = A.class.getDeclaredFields();

答案 1 :(得分:2)

import java.lang.reflect.Field;

abstract class A {
    private final String secret = "got it";
}

class B extends A {
    private final String secret = "try again";
}

public class Test {

    public static void main(String[] args) throws IllegalAccessException {
        Class neededType = String.class;
        A a = new B();
        Class c = a.getClass();
        Class sc = c.getSuperclass();
        Field flds[] =  sc.getDeclaredFields();
        for (Field f : flds) {
            if (neededType.equals(f.getType())) {
                f.setAccessible(true);
                System.out.println(f.get(a));
            }
        }
    }

}

答案 2 :(得分:2)

您需要在A类本身上调用 getDeclaredFields(),然后使用反射来设置可访问的字段

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class Test{

  public static void main(String args[]){
    B someB = new B();
    B otherB = new B();

    Field uniqueField = null;

    for(Field f : A.class.getDeclaredFields()){
      if(!Modifier.isFinal(f.getModifiers()))
        continue;
      if(!UNIQUE.class.isAssignableFrom(f.getType()))
        continue;

      uniqueField = f;
      break;
    }
    if(null == uniqueField)
      throw new NullPointerException();

    uniqueField.setAccessible(true);

    try{
      System.out.println(uniqueField.get(someB) != uniqueField.get(otherB));
    }catch(IllegalArgumentException | IllegalAccessException e){
      throw new RuntimeException(e);
    }
  }

}

class UNIQUE{
}

class A{
  private final UNIQUE u;
  private final String someOtherMember = "";

  A(){
    u = new UNIQUE();
  }

}

class B extends A{

}

如果您没有直接引用A类,或者如果有多个超类具有此唯一字段,那么您可以遍历每一个(确保在每个站点检查您没有全部攀爬)通过在上面的例子中做更像这样的事情来对象的方式

  Class<?> clazz = someB.getClass();
  classClimb: do{
    for(Field f : clazz.getDeclaredFields()){
      if(!Modifier.isFinal(f.getModifiers()))
        continue;
      if(!UNIQUE.class.isAssignableFrom(f.getType()))
        continue;

      uniqueField = f;
      break classClimb;
    }
  }while(Object.class != (clazz = clazz.getSuperclass()));
  if(null == uniqueField)
    throw new NullPointerException();

  uniqueField.setAccessible(true);

  try{
    System.out.println(uniqueField.get(someB) != uniqueField.get(otherB));
  }catch(IllegalArgumentException | IllegalAccessException e){
    throw new RuntimeException(e);
  }

请记住,在这种情况下,您必须对每个对象进行反射,进行一些缓存,或者拥有特定于每个预期超类的多个反射网站。