web-dev-qa-db-fra.com

Type safety: distribution non contrôlée de l'objet

J'essaie de convertir un objet dans ma classe Action, mais un avertissement est généré:

Type safety: Unchecked cast from Object to Action<ClientInterface>

Action<ClientInterface> action = null;
try {
 Object o = c.newInstance();
 if (o instanceof Action<?>) {
  action = (Action<ClientInterface>) o;
 } else {
  // TODO 2 Auto-generated catch block
  throw new InstantiationException();
 }
 [...]

Merci pour toute aide

35
Matthew

Oui, c’est une conséquence naturelle de type gomme . Si o est en fait une instance de Action<String> qui ne sera pas interceptée par le casting, vous ne verrez le problème que lorsque vous essayez de l'utiliser, en passant une ClientInterface à la place d'une chaîne.

Vous pouvez vous débarrasser de l'avertissement en utilisant:

@SuppressWarnings("unchecked")

comme une annotation de fonction, mais vous ne pouvez pas résoudre facilement le problème sous-jacent :(

58
Jon Skeet

Comme d'habitude, Jon Skeet a raison.

Pour élaborer sur la partie difficile de sa réponse:

Donné 

class ClientAction implements Action<ClientInterface> {}

Tu peux écrire:

Class<? extends Action<ClientInterface>> c = ClientAction.class;
Action<ClientInterface> action = c.newInstance();

Cela élimine à la fois la conversion et l'avertissement, au prix de l'introduction d'un type non générique afin que vous puissiez utiliser .class pour obtenir un objet Class suffisamment typé.

14
meriton

L'avertissement signifie que le compilateur ne peut pas garantir la sécurité du type même si le transtypage fonctionne correctement à l'exécution. En raison de l'effacement, au moment de l'exécution, le casting est simplement un casting pour Action. Il est possible que la classe générique sous-jacente ne soit pas de type ClientInterface comme prévu. Dans ce cas, le problème apparaîtra plus tard (peut-être même beaucoup plus tard) sous forme d'exception ClassCastException. 

Dans ce cas spécifique, je recommande de supprimer cet avertissement spécifique à l'aide de la directive de compilation suivante:

@SuppressWarnings("unchecked")
6
Eyal Schneider

Ne t'inquiète pas pour. C'est parce que le compilateur Java n'a aucun moyen de savoir quel est le type réel de l'objet.

2
Petar Minchev

Vous avez perdu les informations de type en raison de l'effacement (c'est-à-dire que les types paramétrés ont été effacés), d'où l'avertissement. Vous ne pouvez rien y faire, à part nettoyer le code qui l'entoure afin que les génériques soient utilisés plus fréquemment, afin que vous puissiez transmettre les informations de type génériques et éviter toute diffusion.

1
Chris Dennett

Ceci est une baisse. C'est le casting dynamique où le compilateur n'a aucune idée de l'objet réel pointé par la référence. 

Vous recevez cet avertissement, car le type cible de la conversion Action<ClientInterface> est un type paramétré et le compilateur ne peut pas garantir que l'objet en cours de conversion est du même type.

Si vous ne souhaitez pas supprimer cet avertissement et que vous ne vous souciez pas du paramètre type, vous pouvez modifier le code en utilisant des caractères génériques:

Action<?> action = null;
try {
 Object o = c.newInstance();
 if (o instanceof Action<?>) {
  action = (Action<?>) o;
 } else {
  // TODO 2 Auto-generated catch block
  throw new InstantiationException();
 }
 [...]

Ceci est beaucoup plus sûr car la instanceof ne peut pas vérifier que o est un objet de Action<ClientInterface>, il vérifie simplement si o est un objet de Action car les informations de type génériques suivantes seront effacées à l'exécution.

0
upupming