2014-10-05 1 views
2

다음과 같은 이유 때문에 "참조가 모호합니다"로 작동하지 않는 이유를 알고 싶습니다. javac 팀에보고 할 가치가 있습니까? 모두 CheckedFunctionCheckedToLongFunction 그렇게 명시 적으로 람 바어의 입력 형식이 유용 아무것도 추가하지 보인다 지정 참조 형식을 가지고 있기 때문에 왜이 람다 관련 형식 유추가 실패합니까?

import java.util.function.Function; 
import java.util.function.ToLongFunction; 
import org.junit.Test; 

public class LambdaTest { 

    @FunctionalInterface 
    public static interface CheckedFunction<U,R> 
    { 
     R apply(U value) throws Exception; 
    } 

    @FunctionalInterface 
    public static interface CheckedToLongFunction<T> 
    { 
     long apply(T i) throws Exception; 
    } 

    public static <T,R> Function<T,R> unchecked(CheckedFunction<T,R> func) 
    { 
     return value -> { 
      try 
      { 
       return func.apply (value); 
      } 
      catch(RuntimeException e) 
      { 
       throw e; 
      } 
      catch(Exception e) 
      { 
       throw new RuntimeException(e); 
      } 
     }; 
    } 

    public static <T> ToLongFunction<T> unchecked(CheckedToLongFunction<T> func) 
    { 
     return value -> { 
      try 
      { 
       return func.apply (value); 
      } 
      catch(RuntimeException e) 
      { 
       throw e; 
      } 
      catch(Exception e) 
      { 
       throw new RuntimeException(e); 
      } 
     }; 
    } 

     public void 
    bar(Function<Object,Object> fn) { 

      System.out.println("Function"); 
     } 

     @Test public void 
    test() { 

      bar (a -> a); //OK 
      bar (unchecked (a -> a)); //Should be OK, but receive "reference to unchecked is ambiguous" 
      bar (unchecked ((Object a) -> a)); //OK 
     } 

} 

당신이 볼 수 있듯이

는 예는 재미있다. 그러나 코드를 컴파일 할 수 있습니다.

unchecked(CheckedToLongFunction)은 프리미티브를 반환하는 람다를 생성하기 때문에, 을 필요로하므로 unckeched(CheckedFunction)을 모호하지 않게 호출해야합니다.

저는 특히 JLS의 해결책을 찾고 있습니다. JLS가 이것을 지정하지 않으면 javac 버그로 제출할 수 있습니다.

답변

1

함수 선언 unchecked(CheckedToLongFunction<T> func)ToLongFunction을 반환하고, ToLongFunctionlong을 반환합니다. 당신의 주장에서, 당신은 프리미티브를 리턴하기 때문에이 함수는 무시되어야한다고 주장한다. 그리고 아마도 런타임 예외가 던져 질 것이다.

자동 복싱의 도입과 함께, ToLongFunction의 원시 결과는 Long에 박스로 표시되어 대상이됩니다.

따라서, 이미 같은 맥락에서 ToLongFunction 반환 수 모두 Longlong

따라서 모호 기능.

JLS 15.12.2

1 참조 - 첫 번째 단계 (§15.12.2.2)는 권투 또는 언 박싱 변환 또는 가변 인수에 대응 메소드 호출의 사용을 허용하지 않고 오버 확인을 행한다. 이 단계에서 적용 가능한 방법이 발견되지 않으면 처리는 두 번째 단계로 진행됩니다.

권투 언 박싱시키면서 그런

2- 두 번째 단계 (§15.12.2.3) 과부하 확인을 수행하지만, 여전히 가변 인수에 대응 메소드 호출의 사용을 배제한다. 이 단계에서 적용 가능한 방법이 발견되지 않으면 처리는 세 번째 단계로 진행됩니다.

+2

'ToLongFunction' 유형이 여기에있는 그림에 있어서는 안됩니다. 모호한'unchecked' 호출입니다. 그리고 어떤 경우 든'bar'는'ToLongFunction'이 아닌'Function'을 기대합니다. –

+0

lambda * input * 형식을 지정하면 해상도가 제대로 작동한다는 점을 지적하고 싶습니다. 입력 유형을 지정해도 자동 복싱으로 인한 모호성이 해결되지 않으므로 요인이 아닙니다. –

2

당신은 두 가지 방법

public static <T,R> Function<T,R> unchecked(CheckedFunction<T,R> func) 
public static <T> ToLongFunction<T> unchecked(CheckedToLongFunction<T> func) 

각 기능 인터페이스 유형의 매개 변수가 있습니다.

@FunctionalInterface 
public static interface CheckedFunction<U, R> { 
    R apply(U value) throws Exception; 
} 

@FunctionalInterface 
public static interface CheckedToLongFunction<T> { 
    long apply(T i) throws Exception; 
} 

implicitly typed lambda expressiona -> a 적절한 문맥 주어진 것들 중 하나에 적용될 수있다. 그러나 과부하 해결을 수행 할 때 해당 컨텍스트가 확인되지 않는 것 같습니다.

하지만 그래서 a -> a

에서
bar(unchecked(a -> a)); // Should be OK, but receive 

(Long의 형식 인수가 그 호출 문맥에서 추론 할 수 없기 때문에), 람다 여전히 기능 유형에 적용되는 CheckedToLongFunction 인스턴스로 변환 할 수 없습니다 .

컴파일러는 a -> aCheckedToLongFunction 또는 CheckedFunction으로 변환해야하는지 여부를 결정할 수 없습니다. 두 가지 모두 적용 가능하므로 호출이 모호합니다. 호출 컨텍스트 (및 반환 유형)는 모호성을 해결하기 위해 검사되지 않습니다. 그러나이 경우

,

bar(unchecked((Object a) -> a)); // OK 

우리는 명시 적으로 람다 식을 입력합니다. 람다 본문은 Object 유형의 반환 값으로, 즉 CheckedToLongFunction#apply(..) 메서드의 요구 사항에 맞지 않습니다. 표현식 Object은 내재적으로 유형 long의 표현식으로 변환 될 수 없습니다.

그러므로 다른 적용 가능한 방법이 있으므로 그 중 하나가 선택됩니다.

+0

사실,'bar (체크되지 않은 (a -> new Object()))'도 작동하지 않으므로 리턴 타입을 지정하는 문제는 아닙니다. 호출 컨텍스트가 점검되지 않았다고합니다. 왜 안돼? 거의 컴파일러 버그처럼 보입니다. –

+1

@AleksandrDubinsky 람다 식 'a -> new Object()'는 여전히 _implicitly typed_입니다. 컴파일러는 지금까지만 갈 것입니다. 암시 적으로 입력되므로 표현식의 본문 유형을 확인하지 않습니다. 왜? [읽어보십시오.] (http://docs.oracle.com/javase/specs/jls/se8/html/jls-18.html#jls-18.5.1) 호출이 독립형 일 수 있기 때문에 같습니다. 다른 어떤 것에 대한 인수 나 할당으로 사용되지 않는다면, 그것을 평가하기위한 두 가지 다른 방법 (규칙 집합)을 갖고 싶지는 않습니다. –