67 votes

Génériques Java: type générique défini comme type de retour uniquement

Je suis à la recherche à un certain GXT code GWT et j'ai couru à travers cette utilisation de médicaments Génériques que je ne peux pas trouver un autre exemple de Java tutoriels. Le nom de la classe est - com.extjs.gxt.ui.client.data.BaseModelData si vous voulez regarder tous les code. Voici les principaux:

private RpcMap map;

public <X> X get(String property) {
  if (allowNestedValues && NestedModelUtil.isNestedProperty(property)) {
    return (X)NestedModelUtil.getNestedValue(this, property);
  }
  return map == null ? null : (X) map.get(property);
}

X est défini nulle part ailleurs dans la classe ou n'importe où dans la hiérarchie, et quand j'appuie sur "aller à la déclaration" dans eclipse, il va juste à l' <X> dans le public signature de la méthode.

J'ai essayé d'appeler cette méthode avec les deux exemples suivants pour voir ce qui se passe:

public Date getExpiredate() {
    return  get("expiredate");
}

public String getSubject() {
    return  get("subject");
}

Ils compilent et ne montrent aucun des erreurs ou des avertissements. Je pense que au moins j'aurais à faire un moulage pour obtenir que cela fonctionne.

Est-ce à dire que les Génériques permettent de la magie la valeur de retour qui peut être n'importe quoi et tout faire exploser au moment de l'exécution? Cela semble contraire à ce que les génériques sont censés faire. Quelqu'un peut-il m'expliquer cela et éventuellement me donner un lien vers une partie de la documentation qui explique un peu mieux? J'ai passé par le Soleil du 23 page pdf sur les médicaments génériques et chaque exemple de valeur de retour est définie au niveau de la classe ou dans l'un des paramètres passés dans.

54voto

Joachim Sauer Points 133411

La méthode retourne un type de ce que vous attendez (<X> est défini dans la méthode et est absolument illimité).

C'est très, très dangereux car aucune disposition n'est prévue que le type de retour correspond en fait à la valeur retournée.

Le seul avantage c'est que vous n'avez pas à jeter la valeur de retour de ces génériques méthodes de recherche qui peut renvoyer n'importe quel type.

Je dirais: l'utilisation de telles constructions avec soin, parce que tu perds à peu près tous type de sécurité et un gain de seulement que vous n'avez pas à écrire un cast explicite à chaque appel à l' get().

Et oui: ce joli bien est de la magie noire qui souffle jusqu'au moment de l'exécution et casse tout idée de ce que les génériques devraient atteindre.

39voto

sblundy Points 27163

Le type est déclaré sur la méthode. C'est que "<X>" signifie. Le type est étendue ensuite seulement à la méthode et qui sont pertinents pour un appel particulier. La raison de votre test code compile, c'est que le compilateur essaie de déterminer le type et va se plaindre que si elle ne peut pas. Il y a des cas où vous avez à être explicite.

Par exemple, la déclaration pour l' Collections.emptySet() est

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

Dans ce cas, le compilateur ne peut pas deviner:

Set<String> s = Collections.emptySet();

Mais si elle ne peut pas, vous devez taper:

Collections.<String>emptySet();

5voto

Kyrra Points 316

J'essayais juste de comprendre la même chose avec un GXT classe. Plus précisément j'ai essayé d'appeler une méthode avec la signature de:

class Model {
    public <X> X get(String property) { ... }
}

Pour appeler la méthode ci-dessus à partir de votre code et de le casting X d'une Chaîne je ne les suivants:

public String myMethod(Data data) {
    Model model = new Model(data);
    return model.<String>get("status");
}

Le code ci-dessus va appeler la méthode get et dites-lui que le type retourné par X doivent être retournés comme une Chaîne de caractères.

Dans le cas où la méthode est dans la même classe que toi, j'ai trouvé que je dois l'appeler avec un ".". Par exemple:

this.<String>get("status");

Comme d'autres l'ont dit, c'est plutôt bâclée et dangereuses par la GXT de l'équipe.

2voto

Rich Points 2561

Note intéressante de RpcMap (GXT API 1.2)

get en-tête:

 public java.lang.Object get(java.lang.Object key)
 

Le fait d'avoir un paramètre générique non instancié de <X> a le même effet, sauf que vous n'avez pas à dire "Objet" partout. Je suis d'accord avec l'autre affiche, c'est bâclé et un peu dangereux.

2voto

erickson Points 127945

BaseModelData déclenche des avertissements non contrôlés lors de la compilation, car elle est dangereuse. Utilisé de cette manière, votre code lève une exception ClassCastException au moment de l'exécution, même s'il ne contient aucun avertissement.

 public String getExpireDate() {
  return  get("expiredate");
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X