Stavo esaminando uno dei percorsi Oracle sui generics Java, intitolato "Effects of Type Erasure and Bridge Methods", e non riuscivo a convincermi di una spiegazione fornita. Curioso, ho testato il codice localmente e non riuscivo nemmeno a riprodurre il comportamento spiegato dal sentiero. Ecco il codice rilevante:Problema potenziale con uno dei percorsi Oracle sui generici Java
public class Node<T> {
public T data;
public Node(T data) { this.data = data; }
public void setData(T data) {
System.out.println("Node.setData");
this.data = data;
}
}
public class MyNode extends Node<Integer> {
public MyNode(Integer data) { super(data); }
public void setData(Integer data) {
System.out.println("MyNode.setData");
super.setData(data);
}
}
Il sentiero Oracle sostiene il seguente comportamento di questo frammento di codice:
MyNode mn = new MyNode(5);
Node n = mn; // A raw type - compiler throws an unchecked warning
n.setData("Hello");
Integer x = mn.data; // Causes a ClassCastException to be thrown.
Questo frammento di codice dovrebbe essere simile al seguente dopo la cancellazione del tipo:
MyNode mn = new MyNode(5);
Node n = (MyNode)mn; // A raw type - compiler throws an unchecked warning
n.setData("Hello");
Integer x = (String)mn.data; // Causes a ClassCastException to be thrown.
Non ho capito i cast utilizzati qui o il comportamento. Quando ho provato a fare funzionare questo codice in locale utilizzando IntelliJ con Java 7, ho ottenuto questo comportamento:
MyNode mn = new MyNode(5);
Node n = mn; // A raw type - compiler throws an unchecked warning
n.setData("Hello"); // Causes a ClassCastException to be thrown.
Integer x = mn.data;
In altre parole, la JVM non permetterà un String
da utilizzare con setData()
. Questo è in realtà intuitivo per me e concorda con la mia comprensione dei farmaci generici. Poiché MyNode
mn
è stato creato con Integer
, il compilatore deve trasmettere ogni chiamata a setData()
con Integer
per garantire la sicurezza del tipo (ad esempio un Integer
viene passato).
Qualcuno può fare luce su questo bug apparente nel percorso Oracle?
Penso che dicendo che la pagina è sciolto con il suo linguaggio sta dando troppo credito. Quindi quello che stai dicendo è che la chiamata 'n.setData (" Hello ")' sta effettivamente colpendo il metodo bridge generato dal compilatore, che eseguirà il cast di ogni oggetto passato a 'Integer' prima di chiamare il metodo super. Bene, questo spiega tutto, suppongo, grazie per le intuizioni. –
Tendo a essere pungente per i documenti non validi, ma mi sono abituato al fatto che il reparto pubblichi documenti terribili, in particolare per le API. Ironia della sorte, Java aveva alcuni dei migliori documenti di sempre, quando era giovane. Al giorno d'oggi ... cerco di mantenere il mio disprezzo per me :) – Adam