Skip to content

Latest commit

 

History

History
134 lines (89 loc) · 3.36 KB

리플렉션_보다는_인터페이스를_사용하라.md

File metadata and controls

134 lines (89 loc) · 3.36 KB

리플렉션

리플렉션 기능을 이용하면 임의의 클래스에 접근 가능

클래스의 생성자, 메서드, 필드 등을 가져오고 조작 가능

👉 리플렉션 사용 예시

리플렉션의 단점

  • 컴파일 타임 타입 검사 이점을 받을 수 없다.
    • ex) private 메소드를 호출할 때 setAccessble 하지 않으면 런타임 에러 발생!
  • 코드가 지저분, 너저분, 장황해진다.
  • 성능 이슈
    • 고려해야 하는 요소들이 많아 오버헤드가 발생
    • 컴파일 타임이 아닌 런타임에 동적으로 타입을 분석하고 정보를 가져오므로 JVM을 최적화할 수 없기 때문

결론적으로 Reflection은 애플리케이션 개발보다는 프레임워크나 라이브러리에서 많이 사용된다.

실제로 intellij의 자동완성, jackson 라이브러리, Hibernate 등등 많은 프레임워크나 라이브러리에서 Reflection을 사용하고 있다.

그럼에도 불구하고

사용해야 할 때가 있는 이유는 분명하다. 동적으로 클래스를 생성하고 접근해야 할 때.

☝🏼 리플렉션은 인스턴스 생성에만 쓰기

☝🏼 이렇게 만든 인스턴스는 인터페이스나 상위 클래스로 참조해 사용하기

public interface Crew {

    void setName(String name);

    void sayMyCourseWithName();

}
public class Backend implements Crew {

    private String name;

    @Override
    public void sayMyCourseWithName() {
        System.out.println(name + "은 Backend 입니다.");
    }

    @Override
    public void setName(String name) {
        this.name = name;
    }
}
public class Frontend implements Crew {

    private String name;

    @Override
    public void sayMyCourseWithName() {
        System.out.println(name + "은 Frontend 입니다.");
    }

    @Override
    public void setName(String name) {
        this.name = name;
    }
}
public class Main {

    public static void main(String[] args) throws ClassNotFoundException {

        Class<? extends Crew> crew = null;
        try {
            crew = (Class<? extends Crew>) Class.forName(args[0]);
        } catch (ClassNotFoundException e) {
            System.err.println("그런 클래스 없습니다.");
            System.exit(1);
        }

        Constructor<? extends Crew> crewConstructor = null;
        try {
            crewConstructor = crew.getDeclaredConstructor();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        Crew eden = null;
        try {
            eden = crewConstructor.newInstance(); // new Backend() or new Frontend()
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
            System.err.println("잘못된 요청입니다.");
        }
        eden.setName(args[1]);
        eden.sayMyCourseWithName();
    }
}
java item65.test.Main item65.test.Backend eden

eden은 Backend 입니다.
java item65.test.Main item65.test.Frontend jun

jun은 Frontend 입니다.

정리

🐱 복잡한 특수 시스템(동적으로 클래스 생성 등)을 개발할 때 필요한 강력한 기능

🐱 강력한 기능인만큼 단점이 너무 큼

장점까지 먹어치운 큰 단점

🐱 잘만 사용하면 우리도 프레임워크 컨트리뷰터!