[JAVA] Class 클레스 - getClasss(), forName(), Reflection(리플렉션), newInstance()
SH.Language/Java 2017. 12. 22. 00:06Class클레스란?
자바의 클레스와 인터페이스의 메타데이터(클레스의 이름, 생성자의 정보, 필드 정보, 메소드 정보)등등을 관리 하는 클레스이다.
즉, 클레스 안의 멤버 변수와 메소드 등등의 리턴 타입이라던지...파라메터값 등등을 알 수 있다는 뜻이다.
그 중에서 오늘은 getClass(), forName()를 살펴보고자 한다.
저 두개의 메소드의 공통점은 무엇일까? 일단 힌트는 둘다 Class의 정보를 받아볼수 있는 메소드이다.
코드를 통해 살펴보자..
public final native Class<?> getClass();
public static Class<?> forName(String className) throws ClassNotFoundException { Class<?> caller = Reflection.getCallerClass(); return forName0(className, true, ClassLoader.getClassLoader(caller), caller); }
일단 둘다 공통점은 Class를 return한다는 것이다.
차이점은?
getClass() 같은경우는 Object클레스에 있는 메소드로써 객체를 생성을 한뒤 호출 할 수 있는 메소드이다.
forName() 같은경우는 객체를 생성하기 전에 직접 객체를 얻을 수 있다.
package api_class._class; public class Car { private String model; private String owner; public Car(){ } public Car(String model){ this.model = model; } public String getModel() { return model; } public void setModel(String model) { this.model = model; } public String getOwner() { return owner; } private void setOwner(String owner) { this.owner = owner; } }
package api_class._class; public class ClassExample { public static void main(String[] args) { Car car = new Car(); Class clazz1 = car.getClass(); System.out.println(clazz1.getName()); System.out.println(clazz1.getSimpleName()); System.out.println(clazz1.getPackage().getName()); System.out.println(); try { Class clazz2 = Class.forName("api_class._class.Car"); System.out.println(clazz2.getName()); System.out.println(clazz2.getSimpleName()); System.out.println(clazz2.getPackage().getName()); } catch (ClassNotFoundException e) { System.out.println("존재하지 않은 클레스"); } } }
위의 소스는 단지 클레스의 이름에 대한 정보만 나와있다.. 하지만 생성자, 필드 메소드의 정보도 얻을수 있다고 하였는데?
당연 정보를 얻어 올수 있다!! 이것이 바로 Reflection(리플렉션)이다.
각각의 정보를 얻어 올수 있는 메소드 (생성자 - getDeclaredConstructors(), 필드 - getDeclareFields(), 메소드 - getDeclaredMethods() ) 이다.
이들의 리턴값은 각각의 타입에 대한 배열이다. (왜냐하면,, 여러개 있을수 있으니까?)
하지만 저들의 메소드는 그 클레스에 선언된 것만 가져온다. 만약 상속된 멤버 까지 가져오고 싶다면.. 중간에 Declare를 뺴면된다..? 쉽죠? ㅋㅋ
이제 각각의 정보를 가져오는 소스를 보도록 하자
package api_class._class; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class ReflectionExample { public static void main(String[] args) throws ClassNotFoundException { try { Class clazz = Class.forName("_class.Car"); System.out.println("[생성자 정보]"); Constructor[] constructors = clazz.getDeclaredConstructors(); for(Constructor constructor : constructors){ System.out.print(constructor.getName() + "("); Class[] parameters = constructor.getParameterTypes(); printParameters(parameters); System.out.println(")"); } System.out.println(); System.out.println("[필드 정보]"); Field[] fields = clazz.getDeclaredFields(); for(Field field : fields){ System.out.println(field.getType().getSimpleName() + " " + field.getName()); } System.out.println(); System.out.println("[메소드 정보]"); Method[] methods = clazz.getDeclaredMethods(); for(Method method : methods){ System.out.print(method.getReturnType().getSimpleName() + " " + method.getName() + "("); Class[] parameters = method.getParameterTypes(); printParameters(parameters); System.out.println(")"); } } catch (ClassNotFoundException e) { System.out.println("클레스가 없음"); } } static void printParameters(Class[] parameters){ for(int i=0;i<parameters.length;i++){ System.out.print(parameters[i].getName()); if(i<(parameters.length-1)){ System.out.print(","); } } } }
이제 마지막으로 그렇다면.. 이들을 정보만 알지말고 객체를 new연산자를 이용해서 생성하지 않고, 메소드를 호출하여 사용할 수 있을까?
그것이 바로 newInstance()를 이용하여 사용할 수있다. newInstance()는 new연산자를 이용하여 객체를 생성을 하지않고, 동적으로 객체를 생성하여, runtime시에 발생을 하게 된다.
package api_class._class; public interface Action { public void execute(); }
package api_class._class; public class ReceiveAction implements Action{ @Override public void execute() { System.out.println("데이터를 받습니다."); } }
package api_class._class; public class SendAction implements Action{ @Override public void execute() { System.out.println("데이터를 보냅니다."); } }
package api_class._class; public class NewInstanceExample { public static void main(String[] args) { try { Class clazz = Class.forName("_class.ReceiveAction"); Action action = (Action) clazz.newInstance(); action.execute(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } }
'SH.Language > Java' 카테고리의 다른 글
[JAVA] Wrapper 클레스 (0) | 2018.01.04 |
---|---|
[JAVA] String, StringBuffer, StringBuilder 클레스 (0) | 2018.01.02 |
[JAVA] Object클레스 - clone() (0) | 2017.12.14 |
[JAVA] Object클레스 - toString() (0) | 2017.12.11 |
[JAVA] Object클레스 - hashCode() (0) | 2017.12.06 |