package com.russolsen.reflect; public class Employee { public String _firstName; public String _lastName; private int _salary; public Employee() { this( "John", "Smith", 50000); } public Employee(String fn, String ln, int salary) { _firstName = fn; _lastName = ln; _salary = salary; } public int getSalary() { return _salary; } public void setSalary(int salary) { _salary = salary; } public String toString() { return "Employee: " + _firstName + " " + _lastName + " " + _salary; } }Class 객체를 만드는 가장 쉬운 방법은 해당 클래스 객체의 getClass 메소드를 호출하는 것입니다. 아래에 있는 코드는 Employee 객체를 만들고 그것의 Class 객체를 만들어서 클래스에 대한 다양한 정보들을 출력합니다.
package com.russolsen.reflect; import java.lang.reflect.Modifier; public class GetClassExample { public static void main(String[] args) { Employee employee = new Employee(); Class klass = employee.getClass(); System.out.println( "Class name: " + klass.getName()); System.out.println( "Class super class: " + klass.getSuperclass()); int mods = klass.getModifiers(); System.out.println( "Class is public: " + Modifier.isPublic(mods)); System.out.println( "Class is final: " + Modifier.isFinal(mods)); System.out.println( "Class is abstract: " + Modifier.isAbstract(mods)); } }코드를 실행하면 다음과 같은 결과를 확인할 수 있습니다.
Class name: com.russolsen.reflect.Employee Class super class: class java.lang.Object Class is public: true Class is final: false Class is abstract: false예제에서 보이듯이 클래스의 이름과 상위 클래스를 알아내는 것은 다른 접근 메소드들(Getters or Accessors)을 호출하는 것처럼 쉬운 일입니다. 만약 해당 클래스가 public 인지 abstract 인지 final 인지 알고 싶다면 약간 복잡해 집니다. 이 모든 정보가 getModifires에 의해 하나의 int 값으로 패키징되어 넘어오기 옵니다. 다행히 Java는 Modifier 클래스를 통해 getModifiers에서 넘어온 숫자를 가지고 여러 일을 할 수 있는 static 메소드들을 제공해 줍니다.
Class klass = Employee.class;세 번째 방법은 좀 더 흥미로운 방법입니다. 문자열을 통해서 Class 객체를 생성할 수 있습니다. 물론 그 문자열이 클래스 이름을 포함하고 있을 때 말이죠. 다음과 같이 Class 클래스에 있는 forName 을 호출하여 얻을 수 있습니다.
Class klass = Class.forName("com.russolsen.reflect.Employee"); System.out.println( "Class name: " + klass.getName()); System.out.println( "Class super class: " + klass.getSuperclass()); // Print out the rest...forName을 사용할 때 한 가지 주의할 것은 클래스 이름 앞에 완전한 패키지 경로를 붙여줘야 한다는 것입니다. 평범하고 늙은 “Employee” 말고 “com.russolsen.reflect.Employee" 여야만 합니다. forName을 통해 리플렉션 API의 기본적인 강력함(그리고 멋진 것)을 살펴봤습니다. 클래스 이름을 포함한 문자열로 시작할 수도 있고 class로 끝낼 수도 있습니다.
package com.russolsen.reflect; public class NewInstanceExample { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException { Class klass = Class.forName(args[0]); Object theNewObject = klass.newInstance(); System.out.println("Just made: " + theNewObject); } }위 코드를 "com.russolsen.reflect.Employee" 인자와 함께 실행하면 새로운 Employee 객체를 만들게 됩니다.
Just made: Employee: John Smith 50000 Run it again, but this time feed it "java.util.Date" and you will get: Just made: Tue Feb 27 20:25:20 EST 2007간단한 코드 몇 줄로 얼마나 많은 유연성을 얻게 되었는지 생각해보세요. 위에 있는 프로그램은 실제 Employee 나 Date 클래스에 관해 아는 것이 하나도 없지만 각각의 새로운 객체들을 만들 수 있습니다. 이것이야 말로 Java 프로그래밍을 하는 또 다른 방법입니다.
Let"s see how this all works in code: Class klass = Class.forName("com.russolsen.reflect.Employee"); Class[] paramTypes = { String.class, String.class, Integer.TYPE }; Constructor cons = klass.getConstructor(paramTypes); System.out.println( "Found the constructor: " + cons); Object[] args = { "Fred", "Fintstone", new Integer(90000) }; Object theObject = cons.newInstance(args); System.out.println( "New object: " + theObject);생성자들 사이의 차이점은 오직 그것들이 가지고 있는 매개 변수들입니다. 따라서 getConstructor 메소드에 찾고자 하는 생성자에 들어갈 매개변수 각각의 Class들 객체의 배열을 넘겨줍니다. 위에 있는 예제에서는 두 개의 String 그리고 하나의 int를 받는 생성자를 찾게 됩니다. Constructor 객체를 얻은 뒤 새로운 객체를 생성하는 일은 간단합니다. 실제 인자로 들어갈 객체의 배열을 newInstance 메소드를 호출하면서 넘겨주면 됩니다.
이전 글 : WebRowSet으로 최고의 JDBC 만들기(2)
최신 콘텐츠