2013-05-01 2 views
8

y 할당 라인에 유형이 지정되지 않은 경고가있는 이유를 누구나 설명 할 수 있습니까? x 또는 z 지정에 대한 경고는 없습니다.예기치 않은 확인되지 않은 전환 경고

public class Entity<T> 
{ 
    @SuppressWarnings("unchecked") 
    public <TX> Entity<TX> typed(Class<TX> type) 
    { 
     return (Entity<TX>) this; 
    } 

    @SuppressWarnings("unchecked") 
    public static <TX> Entity<TX> typed(Entity<?> entity, Class<TX> type) 
    { 
     return (Entity<TX>) entity; 
    } 

    public static void main(final String[] args) 
    { 
     final Entity<?> a = new Entity<Integer>(); 
     final Entity b = (Entity) a; 

     final Entity<Integer> x = a.typed(Integer.class); 
     final Entity<Integer> y = b.typed(Integer.class); 
     final Entity<Integer> z = typed(b, Integer.class); 
    } 
} 
+2

엔티티'b'는'a'의 형변환 이후에 타입이 없으므로'b.typed (Integer.class) '로 다시 변환 할 때 타입이 없습니다.일반 유형은 클래스 유형과 다릅니다. 그들은 "다운 캐스팅 (downcasted)"될 때 유지되지 않습니다. – Vulcan

답변

6

b 원시 타입 형 Entity,이다. 따라서 자사의 API는 다음과 같습니다

public Entity typed(Class type) 

그래서 당신이 Entity에서 Entity<Integer>로 전환하고 있습니다. 컴파일러는 type 매개 변수와 반환 된 엔터티의 종류와의 상관 관계를 잃어 버렸으므로 검사를 수행 할 수 없습니다.

는 다른 말로하면, 당신은 사용할 수 있습니다

final Entity<Integer> y = b.typed(String.class); 

... 아직도 만 같은 경고 메시지가 나타납니다. x 또는 z과 같은 변경을 시도하면 대신 컴파일 타임 오류가 발생합니다.

편집 : 주석에서 언급했듯이 원시 유형을 사용한다는 사실은 제네릭의 모든 흔적을 제거합니다. JLS section 4.8 가입일

:

비 범용 레거시 코드와 인터페이스 촉진하기

, 그 종류로서 소거를 사용하는 것이 가능하다 (§4.6) 파라미터 화 된 형태 (§4.5) 또는의 소거 요소 유형이 매개 변수화 된 유형 인 배열 유형 (§10.1). 이러한 유형을 원시 유형이라고합니다. section 4.6에서

: 그리고

유형의 삭제는 서명을 매핑 (§8.4.2) 어떤 매개 변수 유형이 없거나 변수를 입력 서명에 생성자 또는 방법. 생성자 또는 메소드 서명 s의 지우기는 s와 동일한 이름과 s에 주어진 모든 형식 매개 변수 유형의 지우개로 구성된 서명입니다.

+1

"형식화 된"메서드 자체는 매개 변수화되어 있습니다. 두 가지 유형 매개 변수가 있습니다. –

+4

@KonstantinKomissarchik : 그건 중요하지 않습니다. 원시 타입의 메소드를 호출하면 모든 것이 사라집니다. –

+0

컴파일러가 원시 형식의 메서드를 호출한다고 말하는 것을 제외하고는. 엔티티에서 엔티티 으로의 할당에서 검사되지 않은 변환을 수행한다고합니다. 유형이 TX로 완전히 지정된 경우. –

0

b에 할당 할 때 유형 ID를 제거하면 "다운 캐스팅"됩니다. b는 이제 타입이 지정되지 않았으므로 유형을 더 이상 알지 못하기 때문에 타입이 지정되지 않은 경고가 표시됩니다.

final Entity<?> a = new Entity<Integer>(); 

a가 입력되기 때문에, 메소드 호출은 입력 된 a.typed(Integer.class)입니다 :

1
선언에서

.

typed(b, Integer.class)에서이 방법은 일반적인 방법이기 때문에 작동합니다.

그러나

final Entity b = (Entity) a; 

에서

당신은 (대신 Entity의 일반 버전의 원시 형을 사용하여 b에 대한) 꺼져있는 제네릭 그래서 호출 b.typed(Integer.class)는 유형이 지정되지했다. 그래서 경고를받습니다.

관련 문제