Как получить доступ к полям класса, который я знаю только по строковому имени? - PullRequest
2 голосов
/ 03 марта 2010

Например, у меня есть класс с именем "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, чтобы показать пользователю, как это сделать!

Frank

Ответы [ 3 ]

3 голосов
/ 03 марта 2010

Вам нужно использовать Отражение . Некоторое время назад я написал некоторые утилиты тегов 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 для этих объектов. Если эти методы являются методами получения, то теперь у вас есть доступ к нужному полю.

EDIT

Посмотрев на код в вашем вопросе, я понял, что вам нужны геттеры и сеттеры для этих атрибутов. Итак, предположим, что вы определили getABC и getXYZ, вот несколько надуманный пример:

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;
}

Вышеуказанный подход является более общим. Если вам нужны только поля, вы можете использовать метод, описанный Джеймсом:

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
}
0 голосов
/ 03 марта 2010

Если вам просто нужны поля класса, вам даже не нужно создавать экземпляр, если вы используете отражение для получения класса, вы можете использовать метод 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) {
}
0 голосов
/ 03 марта 2010

Используйте java.lang.reflect. Сначала используйте ClassLoader, чтобы получить класс для класса, затем вы можете вызвать newInstance, чтобы получить объект, затем вы можете использовать интерфейсы отражения, чтобы получить поля.

Обширный учебник в прямом эфире здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...