2017-01-17 3 views
0

내 응용 프로그램이 확장되면서 새 훅 메소드를 도입 한 종속성과 내 응용 프로그램의 호환성을 보장해야합니다. 새롭게 추가 된 메소드를 소개하는 직접적인 접근법 (선언 된 이전 버전에 의해 무시되고 새로운 메소드에 의해 사용됨)은 선언 된 유형의 부속 유형 인 리턴 유형을 정의하자마자 작동을 멈췄습니다.재정의 된 Java 메소드가 존재하더라도 호출되지 않음

오버 헤드 된 메서드를 직접 foo.bar("")으로 호출하면 수퍼 클래스 메서드가 호출됩니다. 그러나 디버거에서 반사를 통해 호출 할 때 foo.getClass().getMethod("bar", String.class).invoke(foo, ""), 예상대로 오버라이드 된 메서드를 호출합니다. 이 메소드는 반환 유형이 동일한 유형으로 좁혀지면 올바르게 호출됩니다. 반환되는 메소드는 이전에 하위 유형이었습니다.

답변

2

covariant return types으로 대체 할 경우, 자바 컴파일러는 선언 대조와 동일한 효과를 갖지만 오버라이드 메소드의 리턴 타입이 브리지 방법를 생성한다. 이것은 JVM이 이름, 인수 목록 및 Java 프로그래밍 언어와 달리 반환 유형으로 메소드를 식별 할 때 필요합니다. 컴파일러는 메소드가 오버라이드되고 리턴 된 유형이 수퍼 클래스의 메소드에 의해 리턴 된 유형의 부속 유형이라는 것을 알고있는 경우에만이를 수행합니다. (이 결정은 @Override 주석에 의존하지 않음에 유의하십시오.)

이 경우, 컴파일러는 새로 추가 된 메소드가 대체가되어야한다는 것을 알지 못합니다 (이전 버전의 종속성이이를 선언하지 않으므로). 따라서 공변량의 리턴 유형을 알 수있는 방법이 없습니다. 결과적으로 JVM이 재정의로 식별 할 수 있도록 브리지 메소드가 생성되지 않으므로 상속 트리를 추가로 메소드 구현을 검색하게됩니다.

해결 방법에는 여러 가지가 있습니다.

  • 확실히 호환성에게 앞으로 이런 식으로 보장 최우선 방법은 부모와 같은 반환 유형이 있는지 확인하십시오. 따라서 브리지 방법이 필요하지 않습니다.
  • 종속성의 새로운 버전을 빌드하고 와 (과)의 호환성을 확인하십시오. 가장 주목할만한 단점은 최소한 지원되는 버전이 예를 들어 maven POM에 의해 선언 된 버전이 아니라는 것입니다.
  • 바이트 코드 조작을 사용하여 명시 적으로 브리지 메소드를 생성하십시오. 나는 독자들에게 그렇게하지 못하도록 링크를 제공하지 않습니다.