2017-02-11 1 views
7

나는 한 다음 클래스 :동일한 이진 바이너리를 사용하는 리턴 유형 일반이 호환 가능합니까?

public abstract Foo { 
    Foo() {} 

    public abstract Foo doSomething(); 

    public static Foo create() { 
    return new SomePrivateSubclassOfFoo(); 
    } 
} 

나는 다음과 같은 정의로 변경하려면 :이 변경 바이너리 호환

public abstract Foo<T extends Foo<T>> { 
    Foo() {} 

    public abstract T doSomething(); 

    public static Foo<?> create() { 
    return new SomePrivateSubclassOfFoo(); 
    } 
} 

인가? 즉, reocmpilation하지 않고 이전 버전의 클래스에서 컴파일 된 코드가 새 버전에서 작동합니까?

SomePrivateSubclassOfFoo을 변경해야한다는 것을 알고 있습니다. 괜찮습니다. 또한 오래된 클라이언트 코드가 컴파일 될 때이 변경으로 인해 원시 형식에 대한 경고가 표시된다는 것을 알고 있습니다. 이는 나에게도 좋습니다. 난 그냥 오래된 클라이언트 코드를 다시 컴파일 할 필요가 있는지 확인하고 싶습니다.

T의 지우기가 Foo이고 따라서 바이트 코드에서 doSomething의 서명이 이전과 동일하기 때문에이 내용을 확인해야합니다. javap -s에 의해 인쇄 된 내부 형식 서명을 보면 실제로 확인 된 것을 볼 수 있습니다 (-s없이 인쇄 된 "비 내부"형식의 서명은 다르지만). 나는 이것을 시험해 보았고 그것은 나를 위해 일했다.

그러나 Java API Compliance Checker은이 두 버전이 바이너리 호환되지 않는다고 알려줍니다.

그래서 무엇이 맞습니까? JLS는 여기서 바이너리 호환성을 보증합니까, 아니면 테스트에서 운이 좋았습니까? (왜 이런 일이 일어날 수 있겠습니까?)

답변

4

그래, 코드가 바이너리 호환성을 해치지 않는 것 같습니다.
나는 말한다있는
http://docs.oracle.com/javase/specs/jls/se8/html/jls-13.html#jls-13.4.5 읽기/일부 크롤링 후 다음을 발견 : -

을 추가 또는 자체로하지 않습니다 클래스의 형식 매개 변수를 제거 바이너리 호환성에 대한 의미를 가지고있다. 소거를 변경할 수 있습니다 클래스의 형식 매개 변수의 첫 번째 바운드 변경
...
(§4.6) 자신의 유형에 해당 유형의 매개 변수를 사용하고,이 바이너리 호환성에 영향을 미칠 수있는 회원의. 이러한 경계의 변경은 메소드 또는 생성자의 유형 매개 변수의 첫 번째 경계 변경과 유사합니다 (13.4.13 절).

그리고이 http://wiki.eclipse.org/Evolving_Java-based_APIs_2#Turning_non-generic_types_and_methods_into_generic_ones 더 관계를 설명 : - 특수 호환성 이야기에 따르면

는, 자바 컴파일러는 유형의 삭제에 대한 참조로 원시 유형을 처리합니다. 기존 유형은 유형 매개 변수를 유형 선언에 추가하고 유형 변수의 사용을 기존 메소드 및 필드의 서명에 알맞게 도입하여 일반 유형으로 발전시킬 수 있습니다. 생성 이전에 해당하는 선언과 같이 지우기가 나타나는 한 변경 사항은 기존 코드와 이진 호환됩니다.

그래서 처음으로 클래스를 생성하기 때문에 문제가 없습니다.

그러나 위의 문서는 말한다 염두에 보관하십시오 : - 이미 제네릭 형식 또는 메서드 양립 진화 할 수있는 방법에 심각한 제약이 있다는 것을 명심,

을하지만, 유형 매개 변수와 관련하여 (위 표 참조). 따라서 API를 생성하려는 경우 올바른 결과를 얻으려면 한 번만 기회 (출시)를 얻는 것을 기억하십시오. 특히 API 서명의 유형을 원시 유형 "List"에서 "List <? >"또는 "List <Object>"으로 변경하면 해당 결정이 잠길 것입니다. 도덕적 인면에서는 기존 API를 생성하는 것이 메소드 별 또는 클래스 별 기준에 따라 단편적인 것이 아니라 전체 API의 관점에서 고려해야하는 것입니다.

제 생각에,이 변경 사항을 처음 작성하는 것이 좋겠지 만 한 번의 기회만으로 충분하게 사용할 수 있습니다!

관련 문제