4


1

Pourquoi et comment ces deux conditions sont-elles traitées différemment par le compilateur?

Les deux exemples de code suivants représentent la même logique. Vérifiez si une chaîne est nulle et branchez-vous en fonction de cette vérification. Le premier échantillon se compile en toute sécurité. Le second produit une erreur de non-concordance de type liée aux génériques Java. Ma question semble assez simple, mais elle m’échappe. Pourquoi le compilateur traite-t-il ces deux instructions différemment? Comment puis-je mieux comprendre ce qui se passe ici?

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


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

L’erreur du compilateur d’Eclipse.

Non-concordance de type: impossible de convertir de Set en Collection

Comme demandé, voici la partie pertinente de l’interface SecurityService.

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

3 Answer


7


Le problème devrait résider dans la façon dont le compilateur interprète la valeur de retour de l’opérateur ternaire. Vous voudrez peut-être jeter un œil sur part 15.25 du JLS ou sur ce https://stackoverflow.com / questions / 8098953 / tricky-ternary-operator-in-java-autoboxing / 8103083 # 8103083 [question] (un peu lié car il est encore plus compliqué par le autoboxing et il génère une erreur au moment de l’exécution plutôt qu’au moment de la compilation).

J’espère que cela vous met dans la bonne direction.


5


C’est parce que Collections.emptySet () renvoie un Set non typé. Essayez plutôt ceci:

Collections.emptySet()


1


  • Collections.emptySet () * est déclaré comme

public static final  Set emptySet()

Le premier * T * est utilisé pour Type Inference. La deuxième implémentation * getUserRoles * est trop complexe pour que le compilateur java détecte le bon type. C’est la raison du problème. Solution de contournement:

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