Class klass = Class.forName("com.russolsen.reflect.Employee");getMethods 는 클래스가 가지고 있는 public 메소드 각각에 해당하는 Method 객체의 배열을 반환합니다.
Method[] methods = klass.getMethods();
for(Method m : methods )
{
System.out.println( "Found a method: " + m );
}
Found a method: public java.lang.String com.russolsen.reflect.Employee.toString()getMethods는 클래스의 사용자(client) 입장이기 때문에, 배열에는 자신이 가지고 있는 모든 public 메소드 (Object 까지 달하는 모든 상속 계층의 상위 클래스들에 있는 public 메소드까지 포함하여)를 배열에 담아 줍니다.
Found a method: public int com.russolsen.reflect.Employee.getSalary()
Found a method: public void com.russolsen.reflect.Employee.setSalary(int)
Found a method: public native int java.lang.Object.hashCode()
Found a method: public final native java.lang.Class java.lang.Object.getClass()
Found a method: public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
Found a method: public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
Found a method: public final void java.lang.Object.wait() throws java.lang.InterruptedException
Found a method: public boolean java.lang.Object.equals(java.lang.Object)
Found a method: public java.lang.String java.lang.Object.toString()
Found a method: public final native void java.lang.Object.notify()
Found a method: public final native void java.lang.Object.notifyAll()
Class klass = Class.forName("com.russolsen.reflect.Employee");리플렉션을 사용하여 메소드를 호출하는 것은 constuctor를 호출하는 것과 매우 유사합니다. 앞서 살펴봤던 Method 객체만 있으면 되고 메소드에 인자로 넘겨 줄 배열과 메소드를 호출할 객체가 필요합니다. 아래에 있는 코드는 우리 직원에게 월급을 올려주기 위해서 Employee 객체에 있는 setSalary 메소드를 호출합니다.
Class[] paramTypes = {Integer.TYPE };
Method setSalaryMethod =
klass.getMethod("setSalary", paramTypes);
System.out.println( "Found method: " + setSalaryMethod);
Class klass = Class.forName("com.russolsen.reflect.Employee");그냥 theObject.setSalary(9000)를 호출하지 않고 왜 그렇게 귀찮게 했을까요? 위에 있는 코드를 자세히 살펴보시길 바랍니다. 코드의 첫 번째 줄을 빼면 위에 있는 프로그램은 완전히 일반적입니다. 어떤 클래스의 어떤 객체든 상관없이 setSalary 메소드를 호출할 것입니다. 약간만 수정하면 어떤 클래스의 어떤 객체든 거기에 있는 모든 메소드를 호출하는 코드로 사용할 수 있습니다.
Class[] paramTypes = {Integer.TYPE };
Method setSalaryMethod =
klass.getMethod("setSalary", paramTypes);
Object theObject = klass.newInstance();
Object[] parameters = { new Integer(90000) };
setSalaryMethod.invoke(theObject, parameters);
Class klass = Class.forName("com.russolsen.reflect.Employee");Employee 가 두 개의 public 필드를 가지고 있기 때문에 두 개의 멤버를 가진 배열을 얻게 됩니다.
System.out.println( "Class name: " + klass.getName());
Field[] fields = klass.getFields();
for(Field f : fields )
{
System.out.println( "Found field: " + f);
}
Class name: com.russolsen.reflect.EmployeegetField메소드를 사용하여 특정 필드 하나만 가져올 수도 있습니다.
Found field: public java.lang.String com.russolsen.reflect.Employee._firstName
Found field: public java.lang.String com.russolsen.reflect.Employee._lastName
Field field = klass.getField("_firstName");Field 객체를 가지고 get 메소드를 호출하면 필드가 가진 값을 가져올 수 있고 set을 사용하여 값을 설정할 수 있습니다.
System.out.println("Found field: " + field);
Object theObject = new Employee("Tom", "Smith", 25);위에 있는 코드를 실행하고 _firstName 필드가 변하는 것을 주의 깊게 살펴보시기 바랍니다.
Class klass = Class.forName("com.russolsen.reflect.Employee");
Field field = klass.getField("_firstName");
Object oldValue = field.get(theObject);
System.out.println( "Old first name is: " + oldValue);
field.set( theObject, "Harry");
Object newValue = field.get(theObject);
System.out.println( "New first name is: " + newValue);
Old first name is: Tom규칙 깨기
New first name is: Harry
ArrayList list = new ArrayList();private 메소드를 받은 뒤에 간단히 setAccessable 안전장치를 제거하고 호출하면 됩니다.
list.add("Larry");
list.add("Moe");
list.add("Curley");
System.out.println("The list is: " + list);
Class klass = list.getClass();
Class[] paramTypes = { Integer.TYPE, Integer.TYPE };
Method m = klass.getDeclaredMethod("removeRange", paramTypes);
Object[] arguments = { new Integer(0), new Integer(2) };
m.setAccessible(true);
m.invoke(list, arguments);
System.out.println("The new list is: " + list);
The list is: [Larry, Moe, Curley]removeRange 메소드는 리스트에서 주어진 범위의 아이템을 제거하는 것처럼 보입니다. 이것은 매우 강력한 마술입니다. java.util 에 있는 클래스에 접근하여 그 안에 있는 private 메소드를 호출할 수 있습니다. 이것을 사용하여 코드의 의도를 우회하여 private 메소드를 호출하는 취미를 즐기실 건가요? 아니죠! 그러나 저런 것들이 약간은 유용할 때가 있습니다.
The new list is: [Curley]
SSISO Community