리플렉션을 사용하면 프로그램,에서 임의의 클래스에 접근할 수 있다. Class 객체가 주어지면 그 클래스의 생성자, 메서드, 필드에 해당하는 Constructor
, Method
, Field
인스턴스를 가져올 수 있고, 이어서 이 인스턴스들로 그 클래스의 멤버 이름, 필드 타입, 메서드 시그니처 등을 가져올 수 있다. 해당 클래스의 인스턴스를 생성하거나, 메서드를 호출하거나, 필드에 접근할 수 있다는 뜻이다. 예를 들어서 Method.invoke
는 어떤 클래스의 어떤 객체가 가진 어떤 메서드라도 호출할 수 있게 해준다. 리플렉션을 이용하면 컴파일 당시에 존재하지 않던 클래스도 이용할 수 있지만 단점이 있다.
이런 단점들 때문에 의존관계 주입 프레임워크처럼 리플렉션을 써야하는 도구들마저 리플렉션 사용을 점차 줄이고 있다. 애플리케이션에 리플렉션이 필요한지 확신할 수 없다면 아마도 필요 없을 가능성이 클 것이다.
리플렉션은 아주 제한된 형태로만 사용해야 그 단점을 피하고 이점만 취할 수 있다. 컴파일타임에 이용할 수 없는 클래스를 사용해야만 하는 프로그램을 비록 컴파일타임이라고 적절한 인터페이스나 상위 클래스를 이용할 수 있을 것이다. 다행히 이런 경우라면 리플렉션은 인스턴스 생성에만 쓰고, 이렇게 만든 인스턴스는 인터페이스나 상위 클래스로 참조해서 사용하자.
리플렉션으로 코드를 작성할때는 단점이 많다. 런타임에 많은 수의 예외를 던진다. 대부분 리플렉션 없이 인스턴스를 생성했다면 컴파일타임에 잡을 수 있는 오류들이다. 두번째로는 코드가 장확하게 길어지며 복잡해진다.
드물지만 리플렉션은 런타임에 존재하지 않을 수도 있는 다른 클래스, 메소드, 필드와의 의존성을 관리할 때 적합하다. 이 방법은 버전이 여러 개 존재하는 외부 패키지를 다룰 때 기동을 위한 최소 환경 즉, 가장 오래된 버전만 지원하도록 컴파일한 후 이후 버전의 클래스와 메소드 등은 리플렉션으로 접근하는 방식이다.