Почему и как эти два условия обрабатываются компилятором по-разному? - PullRequest
4 голосов
/ 24 января 2012

Следующие два примера кода представляют одну и ту же логику.Проверьте, является ли строка нулевой и разветвленной на основе этой проверки.Первый пример компилируется безопасно.Вторая выдает ошибку несоответствия типов, связанную с обобщениями 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интерфейс.

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

Ответы [ 3 ]

7 голосов
/ 24 января 2012

Проблема должна заключаться в том, как компилятор интерпретирует возвращаемое значение троичного оператора.Возможно, вы захотите взглянуть на часть 15.25 JLS или на этот вопрос (вроде как связанный, потому что он еще более усложняется при автобоксировании и выдает ошибку во время выполнения, а не при компиляциивремя).

Надеюсь, это направит вас в правильном направлении.

5 голосов
/ 24 января 2012

Это потому, что Collections.emptySet() возвращает нетипизированный Set. Вместо этого попробуйте это:

Collections.<String>emptySet()
1 голос
/ 24 января 2012

Collections.emptySet () объявлен как

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

Первый T используется для Тип вывода . Вторая реализация 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);
}
...