如何访问类的类字段,我只知道它的字符串名称?

时间:2010-03-02 21:40:50

标签: java reflection class field classloader

例如,我有一个名为“My_Class_X123.java”的类,如下所示:

public class My_Class_X123    // This file was generated by a java program
{
  static String ABC[]={"1","2",...};
  int XYZ=0;
}

当我编写程序时,我不知道会有这个名称的类,但是在运行时我发现了一个名为“My_Class_X123.java”的类存在,我想使用它的字段如ABC和XYZ上面,如何获得这些值?


好的,我得到了答案,就是这样:

  try
  {
    Class myClass=Class.forName("My_Class_X123");
    Field fields[]=myClass.getDeclaredFields();
    String New_ABC[]=String[].class.cast(fields[0].get(String[].class));
  }
  catch (Exception e) { e.printStackTrace(); }

在java doc中有一些像这样的示例代码,向用户展示如何做到这一点不是很好!

3 个答案:

答案 0 :(得分:3)

您需要使用Reflection。前段时间我wrote一些JSTL标签实用程序执行此类操作。一个函数检查一个类是否是传入字符串的实例(基本上是instanceof)。另一个检查以查看类是否具有指定的属性(hasProperty)。以下代码段应该有所帮助:

//Checks to see if Object 'o' is an instance of the class in the string "className"
public static boolean instanceOf(Object o, String className) {
    boolean returnValue;

    try {
        returnValue = Class.forName(className).isInstance(o);
    }

    catch(ClassNotFoundException e) {
        returnValue = false;
    }

    return returnValue;
}

//Checks to see if Object 'o' has a property specified in "propertyName"
public static boolean hasProperty(Object o, String propertyName) {
    boolean methodFound = false;
    int i = 0;

    Class myClass = o.getClass();
    String methodName = "get" + propertyName.toUpperCase().charAt(0) + propertyName.substring(1);
    Method[] methods = myClass.getMethods();

    while(i < methods.length && !methodFound) {
        methodFound = methods[i].getName().compareTo(methodName) == 0;
        i++;
    }

    return methodFound;
}

特别注意第一个方法中的Class.forName方法(加载并初始化一个类)和第二个函数中的getMethods()方法,该方法返回为类定义的所有方法。

你可能想要的是Class.forName,它也初始化了这个类。之后,您可以使用newInstance获取该类的新实例(如果需要)。要访问这些字段,您需要使用从Method获得的getMethod()个对象。对这些对象使用invoke方法。如果这些方法是getter方法,那么您现在可以访问所需的字段。

修改

在查看问题中的代码后,我意识到您需要获取这些属性的getter和setter。因此,假设您定义了getABCgetXYZ,这是一个有点人为的例子:

public Object reflectionDemo(String className, String getter) throws ClassNotFoundException, NoSuchMethodException {

   Object fieldValue;
   Class myClass = Class.forName(className);
   Object myClassInstance = myClass.newInstance(); //to get an instance of the class       

   if(myClassInstance instanceof My_Class_X123) {       
      //null because we are not specifying the kind of arguments that class takes
      Method getterMethod = myClass.getMethod(getter, null); 
      //null because the method takes no arguments
      //Also in the scenario that the method is static one, it is not necessary to pass in an instance, so in that case, the first parameter can be null.
      fieldValue = getterMethod.invoke(myClassInstance, null);
   } 

   return fieldValue;
}

上述方法更通用。如果您只想要字段,那么您可以使用James描述的方法:

myClass = null;
try {
  myClass = Class.forName(className);
  Field[] fields = myClass.getDeclaredFields();

  for(Field field : fields) {
    //do whatever with the field. Look at the API reference at http://java.sun.com/javase/6/docs/api/java/lang/reflect/Field.html    
  }
}

catch(Exception e) {
  //handle exception
}

答案 1 :(得分:0)

使用java.lang.reflect。首先使用ClassLoader获取类的Class,然后可以调用newInstance来获取对象,然后可以使用反射接口来获取字段。

现场综合教程here

答案 2 :(得分:0)

如果您只需要类字段,甚至不需要创建实例,只要您使用反射来获取类,您可以使用getDeclaredFields()方法获取字段的名称及其价值观,例如

Class myClass = null;

try {
    myClass = Class.forName("package.ClassName");
    Field[] fields = myClass.getDeclaredFields();

    for (Field field : fields) {
         System.out.println("Field type is: " + field.getType());
         System.out.println("Field name is: " + field.getName());
    }
} catch (Exception e) {
}