2017-04-24 4 views
-2

J'ai ces classes avec la méthode:Pourquoi les informations de type Java facultatif sont-elles perdues?

public abstract class Bar<T extends Bar> { 
    Foo myFoo; 
    public Optional<Foo> findFoo() { return Optional.ofNullable(this.myFoo); } 
} 

public class Baz extends Bar<Baz> { 
} 

, où Foo est une classe finale de béton et o est un objet qui s'étend Bar.

Il ok pour obtenir la valeur dans mon test unitaire de cette façon:

Bar bar = new Baz(); 
Optional<Foo> optinalFoo = bar.findFoo(); 
Foo foo = optionalFoo.get(); 

Cependant, lorsqu'il est appelé directement les informations de type est perdu:

Foo foo = bar.findFoo().get(); 

Dans le second exemple le compilateur pense obtenir() retourne un objet au lieu d'un Foo. Pourquoi? Y at-il un moyen de fournir les informations de type au compilateur d'une autre manière?

(je sais que vous devriez éviter d'appeler get() directement, mais étant donné que cela est dans un test unitaire, il est ok si elle jette sur des résultats inattendus.)

+3

questions visant à obtenir l'aide de débogage (« pourquoi est-ce pas le code de travail? ») Doivent comprendre le comportement souhaité, un problème spécifique ou d'une erreur et le code le plus court nécessaire pour le reproduire dans la question elle-même. Les questions sans énoncé de problème clair ne sont pas utiles aux autres lecteurs. Voir: Comment créer un [mcve]. Plus précisément: qu'est-ce que ** o **? – GhostCat

+4

Est-ce que 'Foo' est un type générique ou un type concret? Avoir "une classe avec une méthode" n'est pas suffisamment descriptif pour que nous puissions comprendre le problème ou reproduire le problème. –

+1

il ne compilera pas en raison de 'return.ofNullable'. Qu'est-ce que ça veut dire? – Andrew

Répondre

0

La variable bar utilise le type brut, il manque donc toutes les vérifications de type générique. En définissant le type Optional<Foo> optionalFoo, vous avez également une affectation non cochée (cela signifie que les types seront vérifiés à l'exécution seulement), mais le compilateur voit le type et le .get() fonctionne correctement. Pour corriger, vous devez définir un paramètre générique, par ex.

Bar<? extends Bar> bar = new Baz(); 
0

Bar bar est un type brut. Les types bruts n'ont aucune information générique, c'est tout ou rien. Il n'y a pas un gentil, genre de repli générique. Un exemple est

Map<String, String> map = new HashMap<>(); 
Set<Map.Entry<String, String>> entries = map.entrySet(); 

// however when you use a raw type there is no generic. 
Map map2 = new HashMap(); 
Set<Map.Entry> entries2 = map2.entrySet(); // doesn't work 
Set entries2 = map2.entrySet(); // does work 

Ceci est dû au fait que les types bruts sont fournis uniquement pour la rétrocompatibilité. Dans les versions antérieures à Java 5.0, il n'y avait pas de générique et il fallait donc s'attendre à ce que le type brut n'ait pas de génériques.