From bc5a07f8115683dfdaf21b93e0a806daf320c9ad Mon Sep 17 00:00:00 2001 From: Ian Park Date: Sun, 3 Sep 2023 09:55:44 +0900 Subject: [PATCH] =?UTF-8?q?[item65]:=20=EB=A6=AC=ED=94=8C=EB=A0=89?= =?UTF-8?q?=EC=85=98=EB=B3=B4=EB=8B=A4=EB=8A=94=20=EC=9D=B8=ED=84=B0?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=8A=A4=EB=A5=BC=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=ED=95=98=EB=9D=BC=EB=9D=BC=20(#146)(=EA=B1=B4=ED=98=B8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...54\354\232\251\355\225\230\353\235\274.md" | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 "Ch09/item65/\353\246\254\355\224\214\353\240\211\354\205\230\353\263\264\353\213\244\353\212\224_\354\235\270\355\204\260\355\216\230\354\235\264\354\212\244\353\245\274_\354\202\254\354\232\251\355\225\230\353\235\274.md" diff --git "a/Ch09/item65/\353\246\254\355\224\214\353\240\211\354\205\230\353\263\264\353\213\244\353\212\224_\354\235\270\355\204\260\355\216\230\354\235\264\354\212\244\353\245\274_\354\202\254\354\232\251\355\225\230\353\235\274.md" "b/Ch09/item65/\353\246\254\355\224\214\353\240\211\354\205\230\353\263\264\353\213\244\353\212\224_\354\235\270\355\204\260\355\216\230\354\235\264\354\212\244\353\245\274_\354\202\254\354\232\251\355\225\230\353\235\274.md" new file mode 100644 index 0000000..82af5b6 --- /dev/null +++ "b/Ch09/item65/\353\246\254\355\224\214\353\240\211\354\205\230\353\263\264\353\213\244\353\212\224_\354\235\270\355\204\260\355\216\230\354\235\264\354\212\244\353\245\274_\354\202\254\354\232\251\355\225\230\353\235\274.md" @@ -0,0 +1,106 @@ +# Item 65. 리플렉션보다는 인터페이스를 사용하라 + +### Reflection + +오라클 API 문: + +Reflection is commonly used by programs which require the ability to examine or modify the runtime behavior of applications running in the Java virtual machine. This is a relatively advanced feature and should be used only by developers who have a strong grasp of the fundamentals of the language. With that caveat in mind, reflection is a powerful technique and can enable applications to perform operations which would otherwise be impossible. + +- 리플랙션은 Java 가상 머신에서 실행되는 응용 프로그램의 런타임 동작을 조사하거나 수정해야 하는 프로그램에서 주로 사용된다. +- 이 기능은 상대적으로 고급 기능이므로 언어의 기본 원칙을 잘 이해하고 있는 개발자만 사용해야 한다. +- 이 주의사항을 염두에 두면, 리플랙션은 강력한 기술이다. 그리고 그렇지 않으면 불가능한 작업을 수행할 수 있게 한다. + +
+ +### 올바른 사용 예시 + +**프레임워크나 라이브러리 제작**: +대표적으로 Spring과 같은 프레임워크에서는 리플랙션을 사용하여 객체를 생성하거나 메서드를 호출한다. 사용자가 정의한 클래스와 메서드에 대한 메타 데이터를 얻기 위해 사용한다. + +```java +public Object createInstance(String className) throws Exception { + Class clazz = Class.forName(className); + return clazz.newInstance(); +} +``` + +**제네릭 타입 검사**: +제네릭 정보는 런타임에 지워지기 때문에(타입 소거) 리플랙션을 사용하여 해당 정보를 얻을 수 있다. + +```java +public void genericTypeCheck(T obj) { + Class clazz = obj.getClass(); + System.out.println("제네릭 타입은: " + clazz.getSimpleName()); +} +``` + +
+ +### 잘못 사용한 예시 + +**비공개 필드나 메서드 접근**: +비공개 필드나 메서드에 접근하려고 리플랙션을 사용하는 것은 권장되지 않는다. 그 이유는 개발자가 비공개로 설정한 것은 내부 동작을 위해 숨겨진 것이기 때문이다. + +```java +import java.lang.reflect.Field; + +public class BadReflectionExample { + private String secret = "비밀 정보"; + + public static void main(String[] args) throws Exception { + BadReflectionExample example = new BadReflectionExample(); + Field field = BadReflectionExample.class.getDeclaredField("secret"); + field.setAccessible(true); + System.out.println("비공개 필드 접근: " + field.get(example)); + } +} +``` + +**비효율적인 객체 생성**: +Class.newInstance() 를 사용하여 객체를 생성하는 것은 해당 클래스의 기본 생성자가 호출되지만, 생성자에서 발생하는 예외는 래핑되어 다시 던져진다. 따라서 Constructor.newInstance()를 사용하는 것이 더 안전하다. + +```java +// 잘못된 방식 +Object obj = SomeClass.class.newInstance(); + +// 올바른 방식 +Constructor constructor = SomeClass.class.getDeclaredConstructor(); +Object obj = constructor.newInstance(); +``` + +**타입 안전성 무시**: +리플랙션을 사용하면 컴파일 타임에 확인할 수 있는 타입 안전성을 무시하게 되어 런타임 에러의 위험이 증가한다. + +```java +public void unsafeSet(Object obj, Object value) throws Exception { + Field field = obj.getClass().getDeclaredField("someField"); + field.setAccessible(true); + field.set(obj, value); // 타입 검사가 없다면, 잘못된 타입의 값이 설정될 수 있다. +} +``` + +
+ +### 리플랙션의 단점 + +- `성능 이슈`: 리플랙션은 런타임에 타입을 검사하고 조작하기 때문에 직접 코드를 호출하는 것에 비해 성능 손실이 발생한다. + +- `보안 제한`: 보안 매니저가 설정되어 있는 경우, 리플랙션을 사용하여 접근하려는 클래스나 메서드에 대한 권한이 없을 수 있다. + +- `내부 API 및 변경 가능성`: 리플랙션을 사용하여 접근하는 클래스나 메서드가 미래의 Java 버전에서 변경되거나 사라질 수 있다. 내부 API에 대한 접근은 항상 위험하다. + +- `복잡성 증가`: 리플랙션 코드는 복잡하며 디버깅하기 어렵다. 코드의 가독성도 저하된다. + +결론적으로, 리플랙션은 필요할 때만 사용하고, 그 사용을 최소화해야 한다. 가능하면 컴파일 타임에 알려진 타입과 API를 사용하는 것이 바람직하다. + +
+ +### 정리 + +- 리플렉션은 Java에서 제공하는 매우 강력한 기능이다. 이를 통해 런타임에 객체의 내부 정보를 조사하거나 조작할 수 있다. 특히 프레임워크나 라이브러리의 개발, 플러그인 시스템 구현 등 복잡하고 특수한 시스템을 개발할 때 유용하다. + +- 그러나 이 강력한 기능은 단점도 많다. 성능 이슈, 보안 제한, 코드 복잡성 증가 등이 대표적인 문제점이다. 따라서 리플렉션은 반드시 필요한 경우에만 사용하고, 그 범위를 최소화하는 것이 바람직하다. + +- 특히 객체를 생성할 때는 리플렉션을 사용할 수 있지만, 생성된 객체를 다룰 때는 가능한 적절한 인터페이스나 알려진 상위 클래스로 형변환하여 사용해야 한다. 이렇게 하면 코드의 안정성과 가독성, 유지보수성을 높일 수 있다. + +결론적으로, 리플렉션은 `필요한 경우에만, 그리고 신중하게` 사용해야 하는 기술이다. 가능하면 컴파일 타임에 타입이 알려진, 안전한 방법을 우선적으로 고려해야 한다.