2010-07-15 5 views
7

가능한 중복 :
Is this valid Java?특징 또는 버그 :이 Java 코드가 컴파일되는 이유는 무엇입니까?

나는 컴파일 아래의 Java 클래스를 발견하고 깜짝 놀랐다. 동일한 이름, 인수 개수 및 형식 지우기 유형의 인수가있는 여러 가지 방법이 있습니다. 그러나 다양한 버전의 Sun JDK 1.6 컴파일러를 사용하여 Windows에서 컴파일되고 예상대로 작동합니다. 또한 코드를 호출에서 이클립스 3.6

이 버그 경우에 따라서는

이 그것은 또한 이클립스의 수많은 버전으로 컴파일했다 .... 나이를 위해 주변에 있었다, 그러나 컴파일러 컴파일러하지 않는 그 선박 예상대로 작동합니다. 호출 코드에 모호한 메서드에 대한 오류가 없습니다.

당신은 ErasureExample.class.getMethods() 그들은 방법이 "무시 - 상응하는"경우 JLS에 따르면

가 불법이 될 것입니다 ..... 모든 존재의 서명에 의해 반환되는 방법을 반복하는 경우 - 콜렉션, 콜렉션, 콜렉션 중 어느 것도 오버라이드 (override)와 동등하지 않기 때문에 엄격히 말하지 않는다. Eclipse가 틀린 경우 JDK가 정확하다 ...

기능 또는 버그? 컴파일해야합니까?

/** 
* Demonstrates that a class with methods that differ only by return type can exist. 
* Section 8.4 of the JLS suggests this is an error IFF the methods had 
* override equivalent signatures, which they dont'' 
* 
* 
* From JLS 8.4... 

* It is a compile-time error for the body of a class to declare as members two methods 
* with override-equivalent signatures (§8.4.2) (name, number of parameters, and types 
* of any parameters). 
* 
* Should it compile? 
*/ 
public class ErasureExample { 
    // note the single Collection<Integer> argument... 
    public static int[] asArray(Collection<Integer> vals) { 
     if (vals == null) 
     return null; 

     int idx = 0; 
     int[] arr = new int[vals.size()]; 
     for (Integer i : vals) { 
     arr[idx] = i==null? 0 : i.intValue(); 
     idx++; 
     } 
     return arr; 
    } 

    // same method name as above, type differs only by generics.... surely this violates 8.4 of JLS... 
    public static long[] asArray(Collection<Long> vals) { 
     if (vals == null) 
     return null; 

     int idx = 0; 
     long[] arr = new long[vals.size()]; 
     for (Long i : vals) { 
     arr[idx] = i==null? 0 : i.longValue(); 
     idx++; 
     } 
     return arr; 
    } 

    // same method name as above, type differs only by generics.... surely this violates 8.4 of JLS... 
    public static boolean[] asArray(Collection<Boolean> vals) { 
     if (vals == null) 
     return null; 

     int idx = 0; 
     boolean[] arr = new boolean[vals.size()]; 
     for (Boolean b : vals) { 
     arr[idx] = b==null? false : b.booleanValue(); 
     idx++; 
     } 
     return arr; 
    } 

} 

답변

-3

이러한 방법에는 동일한 서명이 없습니다. 다른 리턴 값과 다른 매개 변수 유형. 네, 제네릭은 큰 차이를 만듭니다. 모든 것이 여기 좋아 보인다.

+7

수정 : 반환 값은 서명의 일부가 아닙니다. – schar

+5

실제로 바이트 코드 수준에서 메소드 설명자에는 반환 유형도 포함되어있어이를 구분할 수 있습니다. 컴파일러는 결과를 저장하는 변수의 유형을 검사하여 컴파일러가 어떤 메소드를 호출해야하는지 알 수 있고 바이트 코드에서 명령어 '설명 메소드가있는 호출 메소드 this-and- 그'. 사양에 따르면 정확하지는 않지만 컴파일러는 지금 허용합니다. 분명히 자바 7에서 그들은 이것을 바꿀지도 모른다. –

+1

이 코드를 조금 연주 한 후 Andrei Fierbinteanu에 대한 설명이 가장 확실합니다. 바이트 코드의 호출은 메서드의 고유 한 숫자 ID를 기반으로하기 때문에 동일한 서명으로 메서드를 컴파일하는 데 실제적인 문제가없는 것으로 보입니다. 일부 컴파일러는 이것을 가능하게하기 위해 일반 정보를 가지고 있다는 사실을 이용합니다. 이로 인해 문제가 발생합니다. ErasureExample.class.getDeclaredMethod ("asArray", Collection.class)는 소스 코드에서 첫 번째 메서드를 반환합니다! 즉 코드 순서를 변경하면 내용이 바뀝니다. –

2

컴파일러는 마지막에 형식 지우기를 수행하지만 컴파일 타임에 메서드를 명확하게 구분할만큼 똑똑합니다. 매개 변수화 제네릭의 전체 요점은 컴파일 타임 형식 안전 검사를 제공하는 것입니다. 유형 지우기는 구현 세부 사항입니다.

관련 문제