문제

Imy 질문은 동적 프록시 및 Java 제네릭을 가진 유형 캐스팅의 동작에 관한 것입니다. 보다 구체적으로, 나는 Dynamic Proxy를 사용하여 Servelet 객체를 악기하고 싶습니다. 재사용 가능성을 높이기 위해 아래와 같이 프록시 객체를 만들기위한 일반 코드 템플릿을 채택했습니다.

@SuppressWarnings("unchecked")
public static <T> T instrument(final T aT) {
    T proxy = (T) Proxy.newProxyInstance(aT.getClass().getClassLoader(), new Class[]{MyServelet.class}, new InvocationHandler() {
        @Override
        public Object invoke(Object aProxy, Method aMethod, Object[] aArgs) throws Throwable {
        ..... instrumentation logic goes here
        }
    });
     System.out.println("proxy class " + proxy.getClass());
     System.out.println("input class " + aT.getClass());
     return proxy;
}

여기서 T는 MyServelet 인터페이스를 구현하는 콘크리트 Servelet 구현 클래스입니다. 그러나 위의 메소드를 실행하면 인쇄합니다.

proxy class class com.sun.proxy.$Proxy0
input class class MyServeletImplementation

그래서 코드 스 니펫에서 유형 캐스팅 문에 어떤 일이 일어 났는지 궁금합니다. 프록시가 MyServelEtimplementation에 캐스팅되지 않았기 때문에 조용히 실패한 것 같습니다. 누군가 나에게 이것에 대해 약간의 빛을 흘릴 수 있습니까? 감사!

도움이 되었습니까?

해결책

이 방법의 실제 컴파일 바이트 코드에서 캐스트가 발생하지 않았습니다. 삭제를 입력하십시오.

바이트 코드를 생성 할 때 컴파일러는 매개 변수 유형의 변수를 해당 매개 변수 유형의 상한과 동일한 유형을 갖는 것으로 취급합니다. Object 유형이 무한한 경우. 그래서 만약 T 귀하의 방법에는 제약이있었습니다 <T extends MyServelet>, 컴파일러는 처리했을 것입니다 proxy 유형의 변수로 MyServelet, 캐스트를 삽입했습니다. 그러나 AS T 무한대이며, 유형의 변수로 취급됩니다. Object - 따라서 캐스트가 없습니다.

다른 팁

동적 프록시의 요점은 반환되는 프록시의 실제 클래스에 신경 쓰지 않는다는 것입니다. 원하는 모든 인터페이스를 구현할 수 있습니다.

Javadocs를위한 newProxyInstance 상태:

보고:

지정된 클래스 로더에 의해 정의되고 지정된 인터페이스를 구현하는 프록시 클래스의 지정된 호출 핸들러가있는 프록시 인스턴스

그래서, newProxyInstance 인스턴스를 반환했습니다 com.sun.proxy.$Proxy0 (그게 든 우리는 정말로 신경 쓰지 않습니다). MyServelet. 당신은 그것을 캐스팅 할 수 있어야합니다 MyServelet a ClassCastException, 왜냐하면 newProxyInstance 해당 인터페이스를 구현하기 위해 클래스를 만들었고, 당신은 그것을 통과함으로써 그것을 지정했습니다. new Class[]{MyServelet.class}.

유형 캐스팅이 실패하지 않은 경우 Java Generics는 다음을 추론했을 것입니다. T ~이다 MyServelet, 아니다 MyServeletImplementation. 아마도 당신이 전화했을 때 instrument, 당신은 이것을 좋아했습니다 :

MyServelet proxy = YourClass.instrument(new MyServeletImplementation());

그래서 캐스트는 그랬습니다 MyServelet 성공해야합니다 MyServeletImplementation, 실패해야합니다.

추가해야 할 이유 @SuppressWarnings("unchecked") 컴파일러가 당신이 뭔가 잘못하고 있다고 경고하려고했기 때문입니다. 억제를 추가함으로써, 당신은 당신이하고있는 일을 알았 기 때문에 신경 쓰지 않는다고 컴파일러에게 말했습니다. 아마도 당신이 왜 당신이 왜 당신이 처음에 경고를 받고 있는지를 쫓지 않았다면 주석을 추가해서는 안 되었습니까?

힌트 : 일반 캐스트 T proxy = (T) 로 바뀝니다 Object proxy = (Object) 컴파일러에 의해. (다른 답변에 언급 된대로 "유형 삭제").

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top