4

다음 두 코드 샘플은 동일한 논리를 나타냅니다. 문자열이 null인지 확인하고 해당 검사를 기반으로 분기하는지 확인합니다. 첫 번째 샘플은 안전하게 컴파일됩니다. 두 번째는 Java 제네릭과 관련된 형식 불일치 오류를 생성합니다. 내 질문은 충분히 단순 해 보이지만 그것은 나를 벗어난다. 왜 컴파일러는이 두 문장을 다르게 취급합니까? 여기서 일어나는 일을 어떻게 더 잘 이해할 수 있습니까?이 두 조건은 컴파일러에서 다르게 취급되는 이유는 무엇입니까?

/* compiles cleanly */ 
protected Collection<String> getUserRoles(Object context, 
     Set<String> mappableRoles) { 
    String cookieValue = extractCookieValue(context); 
    if (cookieValue != null) { 
     return securityService.getRolesForUser(cookieValue); 
    } else { 
     return Collections.emptySet(); 
    } 
} 


/* produces a compiler error */ 
protected Collection<String> getUserRoles(Object context, 
      Set<String> mappableRoles) { 
    String cookieValue = extractCookieValue(context); 
    return cookieValue == null ? Collections.emptySet() 
      : securityService.getRolesForUser(cookieValue); 
} 

Eclipse에서 컴파일러 오류가 발생했습니다. 요청한 바와 같이

Type mismatch: cannot convert from Set<capture#1-of ? extends Object> to Collection<String>

, 여기 SecurityService 인터페이스의 중요한 부분이다. Collections.emptySet()이 지정되지 않은 Set을 반환하기 때문에

public interface SecurityService { 
    public Set<String> getRolesForUser(String userId); 
} 
+1

securityService.getRolesForUser()의 서명을 게시 할 수 있습니까? –

+0

추가됨. 인터페이스에는 메소드가 하나 더 있지만이 예제에서는 호출되지 않습니다. –

답변

7

이 문제점은 컴파일러가 3 진 연산자의 반환 값을 해석하는 방법에 있어야합니다. part 15.25 of the JLS을 보거나이 question (좀 더 복잡한 것은 오토 박싱으로 인해 더 복잡해지며 컴파일 타임 대신 런타임에 오류가 발생하기 때문)을 살펴볼 수도 있습니다.

희망이 있으면 올바른 방향으로 오게됩니다. 제 TType Inference가 사용된다

public static final <T> Set<T> emptySet() 

+0

그러면 캡처 변환 프로세스가 범인임을 알게됩니다. 그 문서의 대부분은 내 머리를 잘 넘어서지만 적어도 제네릭 퍼즐 조각을 지적 할 수 있습니다. 감사. –

5

이 있습니다. 대신 다음을 시도하십시오.

Collections.<String>emptySet() 
+0

그것은 컴파일러 오류를 제거하지는 않지만 그 이유는 무엇입니까? 저는 타입 유추가 왜 삼항 연산자가 아닌 if/else 구조로 만들어 질 수 있는지에 대해 가장 관심이 많습니다. –

+0

사과 - 나는 그 부분을 놓쳤다. @Gevorg는 내가 할 수있는 것보다 훨씬 더 잘 설명하는 링크를 제공합니다. – mike9322

1

Collections.emptySet()는 선언된다. 두 번째 getUserRoles 구현은 Java 컴파일러가 올바른 유형을 탐지하기에는 너무 복잡합니다. 이것이 문제의 원인입니다. 해결 방법 :

protected Collection<String> getUserRoles(Object context, 
      Set<String> mappableRoles) { 
    String cookieValue = extractCookieValue(context); 
    Collection<String> a = null; 
    return cookieValue == null ? a = Collections.emptySet() 
      : securityService.getRolesForUser(cookieValue); 
}