2010-03-02 1 views
2

예를 들어, 내가 클래스는 다음과 같이 "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(); } 

이 어떻게 수행하는 사용자에게 보여주기 위해, 자바 문서에이 같은 몇 가지 예제 코드를 가지고 좋지 않을까 :


OK, 나는 대답을 얻었다,이 같은 뭔가 그것!

프랑

답변

3

Reflection을 사용해야합니다. A back back I 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을 사용하여 해당 클래스의 새 인스턴스를 얻을 수 있습니다 (필요한 경우). 필드에 액세스하려면 getMethod()에서 가져온 Method 개체를 사용해야합니다. 해당 개체에 invoke 메서드를 사용하십시오. 이러한 메소드가 getter 메소드 인 경우 이제 원하는 필드에 액세스 할 수 있습니다.

편집은 문제의 코드를보고 후, 나는 당신이 그 속성에 대한 getter 및 setter 필요하다는 것을 깨달았다. 그래서 가정이 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

하지만 먼저 "o"개체를 얻으려면 어떻게해야합니까? – Frank

+0

예제를 추가했습니다. –

+0

프로그래밍 할 때 클래스의 이름을 모르므로이 줄이 작동하지 않습니다. "if (myClassInstance instanceof My_Class_X123)" – Frank

0

java.lang.reflect를 사용하십시오. 먼저 ClassLoader를 사용하여 클래스의 클래스를 가져온 다음 newInstance를 호출하여 객체를 가져온 다음 리플렉션 인터페이스를 사용하여 필드를 가져올 수 있습니다.

포괄적 인 자습서 라이브 here.

+0

모든 샘플 코드? – Frank

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) { 
} 
+0

오, 멋지다! 어떻게 든 저 한테 미끄러 져서 :) ^^ 질문이 있습니다. 왜 catch 블록 안에 선언 된 필드를 가져 오는 코드가 있습니까? 'myClass'가'null '이되지 않습니까? –

+0

으악, 내가 틀린 장소에 있었는지 알지 못했다! –

+0

필드 이름을 사용하는 대신 필드 값을 사용해야합니다. – Frank

관련 문제