728x90
반응형
리플렉션(reflection)은 기본적으로 Java에서 클래스의 정보를 효율적으로
얻기 위해 개발된 기법입니다. 클래스의 정보를 얻는 방법부터 알아 
보겠습니다. 다음의 예제들을 살펴보겠습니다.


▶ 클래스 정보를 관리하는 도구의 종류

/* 클래스 정보를 다루는 도구 얻기 */
public class Test01 {

  public static void main(String[] args) throws Exception {
    // 1) 인스턴스를 통해서 얻기
    String obj = new String("Hello");
    Class<?> c1 = obj.getClass(); // <?> : 어떤 종류의 클래스든 다 얻어올 수 있다는 의미
    // => 인스턴스만 있으면 그 인스턴스가 어떤 클래스의 객체인지 쉽게 알아낼 수 있다.
    
    
    // 2) class.forName() 메서드를 통해서 얻기
    Class<?> c2 = Class.forName("java.lang.String"); 
    // => 아규먼트가 가리키는 문자열이 없을 수 있기 때문에 예외처리가 필요하다.
    // => 클래스 이름을 문자열로 받을 수 있기 때문에 유지보수가 쉽다.
        
    // 3) 모든 클래스에 내장된 "class" 스태틱 변수를 통해서 얻기
    Class<?> c3 = String.class;
    // => 코딩이 간편하다. 그러나 클래스 이름을 코드로 명시하기 때문에 유지보수가 어렵다.
  }

}


▶ Class 도구를 이용해 클래스의 이름 알아내기


/* Class 도구 사용법 : 클래스 이름 알아내기 */
public class Test02 {

  public static void main(String[] args) throws Exception {
    Class<?> c1 = String.class;
    
    System.out.println(c1.getName());
    System.out.println(c1.getSimpleName());
    System.out.println(c1.getCanonicalName());
  }
}

실행 결과 : java.lang.String String java.lang.String



▶ Class 도구를 이용해 특정 메서드의 리턴 타입 알아내기


/* Class 도구 사용법 : 메서드의 리턴 타입 알아내기 */
import java.lang.reflect.Method;
public class Test05 {

  public static void main(String[] args) throws Exception {
    Class<?> clazz = Math.class;
    
    Method m = clazz.getMethod("sin", double.class);
    System.out.println(m);
    
    Class<?> returnType = m.getReturnType();
    System.out.println(returnType.getName());
  }
}

/*
실행 결과 : 
public static double java.lang.Math.sin(double)
double
*/



▶ Class 도구를 이용해 특정 메서드의 파라미터 타입 알아내기


/* Class 도구 사용법 : 메서드의 파라미터 타입 알아내기 */
import java.lang.reflect.Method;
public class Test06 {

  public static void main(String[] args) throws Exception {
    Class<?> clazz = Math.class;
    
    Method[] methodList = clazz.getMethods();
    for (Method m : methodList) {
      System.out.printf("%s\n", m.getName());
      Class<?>[] paramTypes = m.getParameterTypes();
      for (Class<?> paramType : paramTypes) {
        System.out.printf("--> %s \n", paramType.getName());
      }
      System.out.println();
    }
  }
}



▶ Class 도구를 이용해 메서드 호출하기


/* Class 도구 사용법 : 메서드 호출하기 import java.lang.reflect.Method; public class Test07 { public static void main(String[] args) throws Exception { // 1) 인스턴스 메서드 호출하기 String str = new String("Hello"); Class<?> clazz = String.class; Method m = clazz.getMethod("replace", char.class, char.class); Object returnValue = m.invoke(str, 'l', 'x'); System.out.println(returnValue); // 2) 클래스 메서드 호출하기 clazz = Math.class; m = clazz.getMethod("abs", int.class); returnValue = m.invoke(null, -100); // 스태틱 메서드를 호출할 때는 인스턴스를 null로 설정하라 System.out.println(returnValue); } }



▶ Class 도구를 이용해 인스턴스 생성하기

/* Class 도구 사용법 : 인스턴스 생성하기 */
import java.lang.reflect.Method;
import java.util.Date;
public class Test08 {

  public static void main(String[] args) throws Exception {
    // Class<?> clazz = Date.class;
    Class<?> clazz = Class.forName("java.util.Date");
    Date obj = (Date)clazz.newInstance();
    System.out.println(obj);
  }
}


▶ Class 도구를 이용해 nested class 로딩하기

/* Class 도구 사용법 : nested class 로딩 */
import java.lang.reflect.Method;
import java.util.Date;
public class Test09 {

  static class My {}
  
  public static void main(String[] args) throws Exception {
    Class<?> c1 = My.class;
    Class<?> c2 = step26.Test09.My.class;
    Class<?> c3 = Class.forName("step26.Test09$My");
    
    System.out.println(c1);
    System.out.println(c2);
    System.out.println(c3);
  }
}

/*
실행 결과 :
class step26.Test09$My
class step26.Test09$My
*/


Step 1. MySuper 클래스를 정의하기

──────────────────────────────────────

public class MySuper {
  public int superPublicVar;
  String superDefaulttVar;
  protected boolean superProtectedVar;
  private float superPrivateVar;
  
  public void superPublicM() {}
  void superDefaultM() {}
  protected void superProtectedM() {}
  private void superPrivateM() {}
}



Step 2. MySuper 클래스를 상속한 MyClass 클래스 정의하기

──────────────────────────────────────

public class MyClass extends MySuper {
  public int publicVar;
  String defaultVar;
  protected boolean protectedVar;
  private float privateVar;
  
  public MyClass() {}
  public MyClass(int p1) {}
  public MyClass(String p1, int p2) {}
  
  public void publicM() {}
  void defaultM() {}
  protected void protectedM() {}
  private void privateM() {}
  
  public void m1() {}
  public void m2(int v1) {}
  public void m3(String p1, int p2) {}
}




Step 3. MyClass 클래스의 메서드를 알아내기

──────────────────────────────────────

* Class 도구 사용법 : 클래스의 메서드 알아내기 */
import java.lang.reflect.Method;
public class Test03 {

  public static void main(String[] args) throws Exception {
  // static 환경에서는 this가 없다.  
  test1();
  test2();  
  }
  
  private static void test1() throws Exception {
    Class<?> clazz = MyClass.class;
    
    Method[] methodList = clazz.getMethods(); 
    // 상속 받은 메서드를 포함하여 모든 public 메서드만 추출한다.
    for (Method m : methodList) {
      System.out.println(m.getName());
    }
  }
  
  private static void test2() throws Exception {
    Class<?> clazz = MyClass.class;
    
    Method[] methodList = clazz.getDeclaredMethods(); 
    // 해당 클래스에 선언된 모든 메서드를 추출한다. 
    for (Method m : methodList) {
      System.out.println(m.getName());
    }
  }
  
}




Step 4. MyClass 클래스의 특정 메서드만 추출하기

──────────────────────────────────────


/* Class 도구 사용법 : 클래스의 특정 메서드만 추출하기 */
import java.lang.reflect.Method;
public class Test04 {

  public static void main(String[] args) throws Exception {
    Class<?> clazz = MyClass.class;
    
    Method m = clazz.getMethod("m1");
    System.out.println(m.getName());
    
    // 일치하는 메서드를 찾지 못했을 때? null을 리턴하는 것이 아니라 예외가 발생한다.
    // m = clazz.getMethod("m1", String.class);
    // System.out.println(m);
    
    Method m2 = clazz.getMethod("m2", int.class);
    System.out.println(m2);
    
    Method m3 = clazz.getMethod("m3", String.class, int.class);
    System.out.println(m3);
  }
}
/*
실행 결과 : 
m1
public void step26.MyClass.m2(int)
public void step26.MyClass.m3(java.lang.String,int)
*/


728x90
반응형

'Web Programming > java-jsp' 카테고리의 다른 글

java Generic  (0) 2018.09.05
TDD 테스트 주도 개발방법론  (0) 2018.09.04
JSTL에서 LIST Size  (0) 2018.09.04
For input string: ""  (0) 2018.09.04
Jsoup parser 크롤링  (0) 2018.08.30

+ Recent posts