item 65 SeungminLee - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki

Effective Java 3e μ•„μ΄ν…œ 65λ₯Ό μš”μ•½ν•œ λ‚΄μš©μž…λ‹ˆλ‹€.

λ¦¬ν”Œλž™μ…˜(java.lang.reflect)λ₯Ό μ΄μš©ν•˜λ©΄ 컴파일 νƒ€μž„μ— μ•Œ 수 μ—†λŠ” μž„μ˜μ˜ ν΄λž˜μŠ€κΉŒμ§€ 접근을 ν•  수 μžˆλ‹€. μƒμ„±μžμ™€ λ©”μ„œλ“œλ₯Ό κ°€μ Έμ˜¬ 수 있으며 맴버 이름, ν•„λ“œ νƒ€μž…λ„ κ°€μ Έμ˜¬ 수 μžˆλ‹€. κ°€μ Έμ˜€λŠ” 것 뿐만 μ•„λ‹ˆλΌ μƒμ„±μž, λ©”μ„œλ“œ, ν•„λ“œλ₯Ό μ‹€μ œλ‘œ μ΄μš©ν•  수 μžˆλ‹€. 예λ₯Ό λ“€μ–΄ Method.invoke()λ₯Ό μ΄μš©ν•΄μ„œ λΈ”λŸ¬λ“€μΈ λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€.

//ex1
 TestClass testClass = new TestClass(); // TestClass μ•ˆμ— testClassMethodκ°€ μžˆλ‹€κ³  κ°€μ • 
    Class reClass = testClass.getClass();
    Method[] m = reClass.getDeclaredMethods();
    for (int i = 0 ; i < m.length ; i++) {
        if (m.getName().compareTo("testClassMethod") == 0 &&
            m.getParameterTypes().length == 1) {
            Object[] param = new Object[] {"μΈμžκ°’" };
            m.invoke(testClass, param); //λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•  객체,ν˜ΈμΆœν•  λ©”μ†Œλ“œμ— 전달할 νŒŒλΌλ©”ν„°
        }
    }

//ex2
  Method[] m = TestClass.class.getDeclaredMethods() // ex1κ³Ό λ™μΌν•œ κ²°κ³Όκ°€ λ‚˜μ˜¨λ‹€.

νŽΈλ¦¬ν•œ λ¦¬ν”Œλ ‰μ…˜μ˜ 단점

  • μ»΄νŒŒμΌνƒ€μž„ νƒ€μž… 검사가 μ£ΌλŠ” 이점을 ν•˜λ‚˜λ„ λˆ„λ¦΄ 수 μ—†λ‹€.
        μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” 클래슀, λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•΄λ„ μ»΄νŒŒμΌνƒ€μž„ κ²€μ‚¬μ—μ„œλŠ” λ°œκ²¬ν•˜μ§€ λͺ»ν•΄ λŸ°νƒ€μž„ 였λ₯˜κ°€ λ°œμƒν•œλ‹€.
  • λ¦¬ν”Œλ ‰μ…˜μ„ μ΄μš©ν•˜λ©΄ μ½”λ“œκ°€ μ§€μ €λΆ„ν•˜κ³  μž₯황해진닀
  • μ„±λŠ₯이 떨어진닀
        λ¦¬ν”Œλ ‰μ…˜μ„ μ΄μš©ν•œ λ©”μ†Œλ“œ ν˜ΈμΆœμ€ 일반 λ©”μ†Œλ“œ ν˜ΈμΆœλ³΄λ‹€ 훨씬 λŠλ¦¬λ‹€. λ§€κ°œλ³€μˆ˜κ°€ 없이 intλ₯Ό λ°˜ν™˜ν•˜λŠ” λ©”μ†Œλ“œλ„ λ¦¬ν”Œλ ‰μ…˜μ„ μ΄μš©ν•˜λ©΄ 11λ°°λ‚˜ λŠλ €μ‘Œλ‹€.
λ¦¬ν”Œλ ‰μ…˜μ„ μ¨μ•Όν•˜λŠ” λ³΅μž‘ν•œ μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜ (ex μ½”λ“œ 뢄석 도ꡬ, μ˜μ‘΄κ΄€κ³„ μ£Όμž… ν”„λ ˆμž„μ›Œν¬)μ—μ„œ λ¦¬ν”Œλ ‰μ…˜μ΄ μ“°μ΄κΈ°λŠ” ν•˜λ‚˜  
점차 μ‚¬μš©μ„ μ€„μš”κ°€λŠ” 좔세이닀. λ¦¬ν”Œλ ‰μ…˜μ€ μ•„μ£Ό μ œν•œλœ ν˜•νƒœλ‘œλ§Œ μ‚¬μš©ν•΄μ•Ό κ·Έ 단점을 ν”Όν•˜κ³  이점만 μ·¨ν•  수 μžˆλ‹€.

λ¦¬ν”Œλ ‰μ…˜μ€ μΈμŠ€ν„΄μŠ€ μƒμ„±μ—λ§Œ μ‚¬μš©ν•˜κ³ , λ§Œλ“  μΈμŠ€ν„΄μŠ€λŠ” μΈν„°νŽ˜μ΄μŠ€λ‚˜ μƒμœ„ 클래슀둜 μ°Έμ‘°ν•΄ μ‚¬μš©ν•˜λΌ.

public static void main(String[] args) {


    // 클래슀 이름을 Class 객체둜 λ³€ν™˜
    Class<? extends Set<String>> cl = null;
    try {
      cl = (Class<? extends Set<String>>)  // 비검사 ν˜•λ³€ν™˜, @SuppressWarnings을 μ“°κ³  주석을 달아야 ν•œλ‹€.item27
          Class.forName("java.util.HashSet");
    } catch (ClassNotFoundException e) {
      fatalError("클래슀λ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.");
    }

    // μƒμ„±μžλ₯Ό μ–»λŠ”λ‹€.
    Constructor<? extends Set<String>> cons = null;
    try {
      cons = cl.getDeclaredConstructor(); // java.lang.reflect μ‚¬μš©
    } catch (NoSuchMethodException e) {
      fatalError("λ§€κ°œλ³€μˆ˜ μ—†λŠ” μƒμ„±μžλ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.");
    }

    // μ§‘ν•©μ˜ μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“ λ‹€.
    Set<String> s = null;
    try {
      s = cons.newInstance();  // java.lang.reflect μ‚¬μš©
    } catch (IllegalAccessException e) {
      fatalError("μƒμ„±μžμ— μ ‘κ·Όν•  수 μ—†μŠ΅λ‹ˆλ‹€.");
    } catch (InstantiationException e) {
      fatalError("클래슀λ₯Ό μΈμŠ€ν„΄μŠ€ν™”ν•  수 μ—†μŠ΅λ‹ˆλ‹€.");
    } catch (InvocationTargetException e) {
      fatalError("μƒμ„±μžκ°€ μ˜ˆμ™Έλ₯Ό λ˜μ‘ŒμŠ΅λ‹ˆλ‹€: " + e.getCause());
    } catch (ClassCastException e) {
      fatalError("Set을 κ΅¬ν˜„ν•˜μ§€ μ•Šμ€ ν΄λž˜μŠ€μž…λ‹ˆλ‹€.");
    }

    // μƒμ„±ν•œ 집합을 μ‚¬μš©ν•œλ‹€. μƒμœ„ μΈν„°νŽ˜μ΄μŠ€μΈ Set의 λ©”μ„œλ“œλ₯Ό μ‚¬μš©
    s.addAll(Arrays.asList("a","b","c").subList(1, 3));
    System.out.println(s);
  }

  private static void fatalError(String msg) {
    System.err.println(msg);
    System.exit(1);
  }
}
  1. forName()에 String ν˜•νƒœμ˜ 클래슀 파일λͺ…을 λ„£μ–΄μ£Όλ©΄ ν•΄λ‹Ήν•˜λŠ” 클래슀λ₯Ό λ°˜ν™˜ν•΄μ€€λ‹€. 단, μ‹€μ œ ν΄λž˜μŠ€κ°€ λ§Œλ“€μ–΄μ§„ 것은 μ•„λ‹ˆλΌμ„œ λ©”λͺ¨λ¦¬μ— μ˜¬λΌμ˜€μ§€ μ•Šμ•˜λ‹€.
  2. newInstance() λ₯Ό μ‚¬μš©ν•΄μ„œ 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“€μ–΄μ€€λ‹€.
  3. java.io.reflectκ°€ μ œκ³΅ν•΄μ€€ μƒμ„±μžλ‘œ μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•œ 이후 λΆ€ν„°λŠ” reflect의 κΈ°λŠ₯을 쓰지 μ•Šκ³  μΈν„°νŽ˜μ΄μŠ€λ‚˜ μƒμœ„ 클래슀λ₯Ό μ°Έμ‘°ν•΄μ„œ μ‚¬μš©ν•œλ‹€.

λ¦¬ν”Œλ ‰μ…˜μ˜ 두 가지 단점

λ¦¬ν”Œλ ‰μ…˜μ„ μ‚¬μš©ν•˜μ§€ μ•Šμ•˜λ‹€λ©΄ 컴파일 νƒ€μž„μ— μž‘μ„ 수 μžˆλŠ” 였λ₯˜λ“€μ„ 6κ°€μ§€λ‚˜ λ˜μ§„λ‹€. 클래슀 μ΄λ¦„λ§Œ μ‚¬μš©ν•˜μ—¬ μΈμŠ€ν„΄μŠ€λ₯Ό 생성해내기 μœ„ν•΄ 25μ€„μ΄λ‚˜ λ˜λŠ” μ½”λ“œλ₯Ό μž‘μ„±ν–ˆλ‹€. μƒμ„±μž ν˜ΈμΆœλ‘œλŠ” ν•œμ€„μ΄λ©΄ λœλ‹€.

μ½”λ“œλ₯Ό 쀄이기 μœ„ν•΄ java.io.reflect의 μ΅œμƒμœ„ 였λ₯˜μΈ ReflectiveOperationException 을 μ‚¬μš©ν•΄λ„ λœλ‹€.

image ReflectiveOperationException와 subclass exception

λ¦¬ν”Œλ ‰μ…˜μ€ λŸ°νƒ€μž„μ— μ‘΄μž¬ν•˜μ§€ μ•Šμ„ μˆ˜λ„ μžˆλŠ” λ‹€λ₯Έ 클래슀, λ©”μ„œλ“œ, ν•„λ“œμ™€μ˜ μ˜μ‘΄μ„±μ„ 관리할 λ•Œ μ ν•©ν•˜λ‹€.

  • 버젼이 μ—¬λŸ¬ 개 μ‘΄μž¬ν•˜λŠ” μ™ΈλΆ€ νŒ¨ν‚€μ§€λ₯Ό λ‹€λ£° λ•Œ μœ μš©ν•˜λ‹€.
  • κ°€μž₯ 였래된 λ²„μ Όλ§Œ μ§€μ›ν•˜λ„λ‘ 컴파일 ν•œ ν›„, 이후 λ²„μ Όμ˜ ν΄λž˜μŠ€μ™€ λ©”μ„œλ“œλŠ” λ¦¬ν”Œλ ‰μ…˜μœΌλ‘œ μ ‘κ·Όν•˜λŠ” 방식이닀.
  • 이런 경우 μ ‘κ·Όν•˜λ €λŠ” μƒˆλ‘œμš΄ ν΄λž˜μŠ€λ‚˜ λ©”μ„œλ“œκ°€ λŸ°νƒ€μž„μ— μ‘΄μž¬ν•˜μ§€ μ•Šμ„ 수 μžˆλ‹€λŠ” 사싀을 κ°μ•ˆν•΄μ„œ λŒ€μ²΄ μˆ˜λ‹¨μ„ λ§Œλ“€μ–΄ λ‘¬μ•Όν•œλ‹€.
핡심정리  
λ¦¬ν”Œλ ‰μ…˜μ€ λ³΅μž‘ν•œ μ‹œμŠ€ν…œμ„ κ°œλ°œν•  λ•Œ ν•„μš”ν•œ κ°•λ ₯ν•œ κΈ°λŠ₯μ΄μ§€λ§Œ 단점이 많기 λ•Œλ¬Έμ— λ¦¬ν”Œλ ‰μ…˜μ€ λ˜λ„λ‘ 객체 μƒμ„±μ—λ§Œ μ‚¬μš©ν•˜κ³ , 
μƒμ„±ν•œ 객체λ₯Ό μ΄μš©ν•  λ•ŒλŠ” μ μ ˆν•œ μΈν„°νŽ˜μ΄μŠ€λ‚˜ 컴파일 νƒ€μž„μ— μ•Œ 수 μžˆλŠ” μƒμœ„ 클래슀둜 ν˜•λ³€ν™˜ν•΄μ„œ μ‚¬μš©ν•΄μ•Ό ν•œλ‹€. 
⚠️ **GitHub.com Fallback** ⚠️