2015-01-26 2 views
10

죄송 합니다만 이미 설명했는데 웹에서 비슷한 스레드를 찾지 못했습니다.호환되지 않는 캐스트에 대한 컴파일러 오류가 없습니다.

오늘 IDE에서 하나의 프로젝트 클래스를 열고 프로젝트가 성공적으로 컴파일되었지만 오류 (빨간색 밑줄)가 표시되었습니다.

public interface DatasourceImplementation<T extends Entity> { 
    .... 
} 

public interface Datasource<T extends Entity> { 
    .... 
} 


public interface DsContext { 
    @Nullable 
    <T extends Datasource> T get(String name); 
} 

그리고 지금 우리는이 같은이 메서드를 호출 :

그래서 코드는

DatasourceImplementation dsImpl = getDsContext().get("dsName"); 

Idea13 나에게 오류 (호환되지 않는 유형) 제공을 - 나는 맞아 생각합니다.

Idea14는 여기에 오류를 표시하지 않습니다.

JDK는 오류없이 컴파일합니다. 슬픈 일입니다.

우리의 프로젝트 구현 클래스에서 A 인터페이스는 항상 B 인터페이스를 구현하지만 (생각하면 Idea14에서는 이것이 정상이라고 말하는 이유를 설명 할 수 있습니다.) 제 생각에는이 동작을 정당화 할 수 없습니다 - 일반적으로 클래스를 만들 수 있기 때문에 A를 구현하고 B를 구현하지 않습니다. 내 코드에서 정적 유형 지정을 원하고 런타임 클래스 캐스트 예외를보고 싶지 않습니다.

여기 누가 잘못 되었나요?

업데이트. 실제 클래스와 스크린 샷을 추가

enter image description here

+2

이것은 정말 흥미 롭습니다. 완전한 단순화 된 프로그램을 볼 수 있습니까? –

+0

@RichardTingle이 4 가지 간단한 클래스의 스크린 샷을 추가했습니다. 충분합니까? – AdamSkywalker

+0

코드를 텍스트로 게시하십시오. 첫 번째 생각 : 당신은'get()'메소드에서 일반적인 타입의 데이터 소스를 사용하고 있습니다. –

답변

3

JDK가 올바른지 (뭔가 더 설명 할 것입니다 확실하지를, 내가 설명 단지 동일합니다). 이 선언은 데이터 소스를 반환 하겠지만, 일치하지 않으면 런타임 오류 만 발생합니다. 컴파일러는 몇 가지 심각한 경고를 표시하지만 컴파일해야합니다. 스 니펫의 원래 개발자는 각 통화에 대한 명시 적 캐스트를 피하려고했습니다. 의도에 따라 그것을 해결하는 방법에

다른 방법 :

  1. DataSource<?> get(String name) : 발신자가 DatasourceImplementation으로 캐스팅해야합니다.
  2. <T extends Datasource> T get(Class<T> dsType, String name). 호출 된 함수는 런타임에 반환 된 유형을 확인하거나 선택할 수 있습니다. Impl1 또는 Impl2를 반환합니다.
  3. <T extends Entity>' Datasource<T> get(String name) 이것은 아마도 의도 한 것입니다. DatasourceImplementation이 구체적인 엔티티 유형을 알 필요가없는 한 작동합니다. 그것이 그것을 알 필요가있는 경우에, <T extends Entity>' Datasource<T> get(Class<T> entityType, String name)는 좋을.
+1

나는 당신이 말하는 것을 이해하지만, (X는 inteface 임)을 사용하는 것처럼 들린다. X와 Y 인터페이스간에 클래스 캐스트를 피할 수있다. 이상 하네, 안 그래? – AdamSkywalker

+0

' T f() {return (T) new Integer (1); }': 컴파일러는 f() 내에서만 경고를 표시하지만 f()를 호출 할 때는 경고를 표시하지 않습니다. 입력 매개 변수에 의존하지 않는 반환 유형을 사용하는 이러한 메서드는 실제로는 허술한 허점입니다. 추한 응용 프로그램은 http://stackoverflow.com/a/509324/404501을 참조하십시오. –

+0

좋아, 나는 을 사용하여 가능한 모든 캐스트를 만들 수 있다는 것을 승인 한 몇 가지 테스트를 작성했다. Idea13이 잘못되었습니다 (내 질문에 답하는 것). 코드를 안전하지 않은 것으로 표시해야합니다. – AdamSkywalker

0

언뜻보기에 코드/질문이 약간 이상하게 보입니다.

두 인터페이스가 서로 독립적이며 두 인터페이스 모두 제네릭 유형입니다.

  1. DatasourceImplementation < T는 T는 T이 BOSE T 년대가 동일한 것을 의미하지 않는다 엔티티 >를 확장 <을 가지고 그러나

법인 > 확장 데이터 소스 < 법인 > 및

  • 을 확장합니다. 사실 그것은 전혀 다른 구현 (Entity에서 확장)과 다른 유형으로 캐스트 할 수없는 구현이 모두 가능합니다.

    은 또한 당신은 GET-방법은 데이터 소스를 구현 뭔가를 반환해야 함을 말하는 당신의 인터페이스

    public interface DsContext { 
        @Nullable 
        <T extends Datasource> T get(String name); 
    } 
    

    있습니다. 그러나이 T는 다른 하나의 T와 완전히 독립적입니다. 실제로 컴파일러는 데이터 원본을 원시 형식으로 사용한다고 불평해야합니다.

    대신 <T extends Entity> Datasource<T> get(String name); 을 찾으셨습니까?

    그러나 Datasource와 DatasourceImplementation의 관계가 없으므로 서로 독립적 인 두 가지 유형이 있습니다. java.lang.Stringjava.lang.Number과 같습니다. String 유형으로 선언 된 참조에 숫자를 할당하려고하면 컴파일러 오류가 발생합니다. 따라서 오류를보고하는 컴파일러는 완벽하게 문제가없는 것으로 보입니다.

    코드 조각이 중요한 상속을 놓쳤습니까? 실제로 모든 경우 컴파일러가 실행 되었습니까?

    세바스찬

  • 관련 문제