2014-09-30 3 views
3

이 정말 바보 같은 질문처럼 보이지만이 Optional<T>의 사용은 컴파일 왜 을 이해할 수 없다 :Java : Optional.empty()를 어떻게 사용합니까?

import java.util.Optional; 

public class Driver { 
    static void foo(Optional<String> x) { } 

    public static void main() { 
     foo(Optional.empty()); 
    } 
} 

Optional::empty 나를 Optional<T>를 반환으로 정의된다. Driver::main의 내부에서 Optional.empty()이라는 표현식은 Optional의 사용을 매개 변수화하지 않으므로 Optional<Object>을 반환하는 것처럼 보입니다. 따라서 형식 매개 변수로 Object으로 다시 떨어질 것으로 예상됩니다. 그런 다음 Optional<Object>을 허용하지 않아야하는 매개 변수의 다운 캐스팅 인 Optional<String>을 예상하는 함수에 전달합니다.

incompatible types: Optional<Object> cannot be converted to Optional<String> 

그러나 코드는 완벽하게 잘 컴파일됩니다. 분명히, 내 사고 과정은 부정확하지만 ... 어디서?


답안에서 내가 찾고있는 것을 명확히 해 주겠습니까 ... 어떤 유형 유추인지 알고 있습니다. 어떻게 이해가 안되는가 어떻게 Java 7에서 Java 8로 언어가 바뀌 었는지 여기서 알 수 있습니다. 예를 들어이 코드는 Java 8에서 완벽하게 컴파일되지만 Java 7에서는 실패합니다.

final class Opt<T> { 
    private final T value; 

    Opt(T x) { 
     value = x; 
    } 

    public static <T> Opt<T> empty() { 
     return new Opt<T>(null); 
    } 
} 

public class Driver { 
    static void bar(Opt<String> x) { } 

    public static void main() { 
     bar(Opt.empty()); 
    } 
} 

오버로드와 같은 문제를 해결해야 할 때 Java 8에서 어떻게 작동합니까? 이런 종류의 것에 대해 이야기하는 Java 언어 스펙의 특정 섹션이 있습니까?

+3

유형 유추는 멋진 것이다 –

+0

그 질문에 유용하게 대답하지 않는다. –

답변

9

이 때문에 빈() 메소드는 선택 사양에 정의 된 방식 방식입니다 :

public static<T> Optional<T> empty() { 
    @SuppressWarnings("unchecked") 
    Optional<T> t = (Optional<T>) EMPTY; 
    return t; 
} 

참고 위의 방법 유형 매개 변수 :

public static<T> Optional<T> empty() { 
      ^^^ method type parameter 

이 호출 될 때 빈() 것을 의미한다 , 그것은 당신의 String 인 호출자의 문맥에 T를 묶을 것이다. 더 자세한 정보는 자바 튜토리얼이 페이지에서 대상 유형 섹션을 참조하십시오 컴파일러가 추론을 입력하지

http://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html

+0

+1 매개 변수. 하지만 추측 부분에 대해서는 그렇게 확신하지 못합니다. 형식 매개 변수 선언은 꽤 명백합니다. – rompetroll

-1

Java 8 추가 유형 인터페이스는 사용법에 따라 표현식의 유형을 결정합니다.

blatent 예는

Runnable r =() -> System.out.println("Hello World"); 

Object o = (Runnable)() -> System.out.println("Hello World"); 

잘 컴파일, 그것은 그러나 표현의 유형을 알고하지 않기 때문에

Object o =() -> System.out.println("Hello World"); 

가 컴파일되지 않습니다이다. 즉 표현의 유형은 그것이 사용되는 방식으로 바뀐다.

0

이 있기 때문이다.컴파일러 읽고

는 :

static void foo(Optional<String> x) { } 

public static void main() { 
    foo(Optional.empty()); 
} 
  • Optional.<T>empty()가 매개 변수로 T을 것을 알고있다.
  • foo 그것은 TString 것을 추론 Optional<String>
  • 을 기대하는 것을 알고있다.

Java 8의 javac을 사용하여 도입 된 기능 및 그 메커니즘이 개선되었을 때 도입되었습니다.

ECJ (Eclipse JDT 컴파일러)는 Javac이 이해하는 것과 동일한 자바 소스를 이해하지 못합니다 (그러나 "동일한"바이트 코드를 컴파일 함). 귀하의 질문의 일부가 해결되지 않았기 때문에, 나는 자바 7 및 Java 8

자바 (7) 사이에 변경 한 내용을 요약하려고합니다

8

이미했다 유형 추론, 예를 들어, 당신은

List<String> list=Collections.emptyList(); 

또는

List<String> getList() { 
    return Collections.emptyList(); 
} 

를 작성할 수 그러나 이러한 유형의 추론은 오히려 제한 예를 들면이었다 무엇을 (다른 사람 외에) 작동하지 않은 것은이었다

List<String> list=Collections.unmodifiableList(Collections.emptyList()); 

또는

List<String> getList() { 
    return condition? new ArrayList<>(): Collections.emptyList(); 
} 

이 두 가지 예는이 새로운 기능은 지금 대상의 사용으로 대상 형식 유추라고 자바 (8)에서 지금 작업 적절한 유형 인수를 찾으려면 type을 입력하십시오. 위의 예에서와 같이 중첩 된 메소드 호출 및 조건문 일을하고 게다가, 그것은 또한 다음과 같은 예를 해결

List<Number> numbers=Arrays.asList(1, 2, 3, 4); 

으로 자바 7이 너무 형식 유추했다 말했다, 그러나이 예에서 같이 List<Integer>을 추론 할 asList에 전달 된 인수의 표현식 결과 유형이 오류를 생성합니다. 반면

는 자바 8 대상 형식 유추을 가지고 표현의 유형으로 List<Number>을 추론하고 Integer 개체를 사용할 수있는 전체 명령문이 유효한지 알아 내기 위해 할당의 대상 유형을 사용하는 경우 Number 예상된다.

Optional.empty()Collections.emptyList()은 동일한 종류의 일반 구문을 사용합니다. 나는 자바 7에 이미있는 것처럼 예제에서 후자를 사용했다.

관련 문제