Fragen:
- Was sind Raw-Typen in Java und warum höre ich oft, dass sie nicht in neuem Code verwendet werden sollen?
- Was ist die Alternative, wenn wir keine Raw-Typen verwenden können, und warum ist sie besser?
Was ist ein Raw-Typ und warum höre ich oft, dass sie nicht in neuem Code verwendet werden sollten?
Ein "Raw-Typ" ist die Verwendung einer generischen Klasse ohne Angabe eines Typarguments für ihre parametrisierten Typen, z. B. die Verwendung von List
anstelle von List
. Als Generics in Java eingeführt wurden, wurden mehrere Klassen aktualisiert, um Generics zu verwenden. Die Verwendung dieser Klassen als "Raw-Typ" (ohne Angabe eines Typarguments) ermöglichte es, dass Legacy-Code immer noch kompilierte.
"Raw-Typen" werden aus Gründen der Abwärtskompatibilität verwendet. Ihre Verwendung in neuem Code wird nicht empfohlen, weil die Verwendung der generischen Klasse mit einem Typargument eine stärkere Typprüfung ermöglicht, die wiederum die Verständlichkeit des Codes verbessern und dazu führen kann, potenzielle Probleme früher zu erkennen.
Was ist die Alternative, wenn wir keine Raw-Typen verwenden können, und warum ist sie besser?
Die bevorzugte Alternative besteht darin, generische Klassen wie vorgesehen zu verwenden - mit einem geeigneten Typargument (z. B. List
). Dies ermöglicht es dem Programmierer, Typen genauer anzugeben, vermittelt zukünftigen Wartenden mehr Informationen über die beabsichtigte Verwendung einer Variablen oder Datenstruktur und ermöglicht es dem Compiler, eine bessere Typsicherheit durchzusetzen. Diese Vorteile zusammen können die Codequalität verbessern und dazu beitragen, die Einführung einiger Codierungsfehler zu verhindern.
Zum Beispiel, für eine Methode, bei der der Programmierer sicherstellen möchte, dass eine Listenvariable namens 'names' nur Strings enthält:
List names = new ArrayList();
names.add("John"); // OK
names.add(new Integer(1)); // Kompilierfehler
Ah, so versucht, polygenelubricants
's "raw type" Referenzen von stackoverflow.com/questions/2770111/… in meine eigene Antwort zu kopieren, aber ich denke, ich lasse sie für die Verwendung in seiner/ihrer eigenen Antwort.
Ja, ich habe im Grunde genommen diesen Abschnitt überall kopiert und eingefügt, wo Leute auf Stackoverflow Rohdatentypen verwenden, und habe mich schließlich entschieden, einfach eine Frage zu haben, auf die ich von nun an verweisen kann. Ich hoffe, es ist ein guter Beitrag für die Gemeinschaft.
Hier betrachte ich mehrere Fälle, durch die du das Konzept klarstellen kannst
1. ArrayList arr = new ArrayList();
2. ArrayList arr = new ArrayList();
3. ArrayList arr = new ArrayList();
ArrayList arr
ist eine ArrayList
Referenzvariable mit dem Typ String
, die auf ein ArrayList
-Objekt vom Typ String
verweist. Das bedeutet, dass es nur Objekte vom Typ String halten kann.
Es ist strikt auf String
und nicht auf einen Raw-Typ, daher wird es niemals eine Warnung auslösen.
arr.add("hello");// Einzelne Anweisung wird erfolgreich kompiliert und keine Warnung ausgegeben.
arr.add(23); //anfällig für Kompilierungsfehler.
//Fehler: für add(int) wurde keine geeignete Methode gefunden
In diesem Fall ist ArrayList arr
ein Strikt-Typ, aber Ihr Objekt new ArrayList();
ist ein Raw-Typ.
arr.add("hello"); //alleine wird dies kompiliert, aber eine Warnung ausgegeben.
arr.add(23); //erneut anfällig für Kompilierungsfehler.
//Fehler: für add(int) wurde keine geeignete Methode gefunden
Hier ist arr
ein Strikt-Typ. Daher wird ein Kompilierungsfehler gemeldet, wenn ein Integer
hinzugefügt wird.
Warnung: Eine Raw-Typ-Objekt wird auf eine Strikt-Typ-Referenzvariable von
ArrayList
verwiesen.
In diesem Fall ist ArrayList arr
ein Raw-Typ, aber Ihr Objekt new ArrayList();
ist ein Strikt-Typ.
arr.add("hello");
arr.add(23); //kompiliert gut, aber warnt.
Es wird jedes Objekttyp hinzufügen, weil arr
ein Raw-Typ ist.
Warnung: Ein Strikt-Typ-Objekt wird auf eine Raw-Typ-Referenzvariable verwiesen.
Der Compiler möchte, dass Sie Folgendes schreiben:
private static List list = new ArrayList();
denn ansonsten könnten Sie jeden gewünschten Typ zu list
hinzufügen, was die Instanziierung als new ArrayList()
sinnlos machen würde. Java Generics sind nur ein Feature zur Kompilierzeit, daher wird ein Objekt, das mit new ArrayList()
erstellt wurde, fröhlich Integer
oder JFrame
Elemente akzeptieren, wenn es einem Verweis des "raw type" List
zugewiesen wird - das Objekt selbst weiß nichts darüber, welche Typen es enthält soll, nur der Compiler.
Hier ist ein weiterer Fall, in dem Raw-Typen Sie beißen werden:
public class StrangeClass {
@SuppressWarnings("unchecked")
public X getSomethingElse() {
return (X)"Etwas anderes testen!";
}
public static void main(String[] args) {
final StrangeClass mitGenerisch = new StrangeClass<>();
final StrangeClass ohneGenerisch = new StrangeClass();
final String wert1,
wert2;
// Kompiliert
wert1 = mitGenerisch.getSomethingElse();
// Erzeugt einen Kompilierfehler:
// inkompatible Typen: java.lang.Object kann nicht in java.lang.String konvertiert werden
wert2 = ohneGenerisch.getSomethingElse();
}
}
Dies ist nicht intuitiv, da man erwarten würde, dass der Raw-Typ nur Methoden betrifft, die an den Klassentypparameter gebunden sind, aber tatsächlich betrifft es auch generische Methoden mit ihren eigenen Typparametern.
Wie im akzeptierten Antwort erwähnt wurde, verlieren Sie jegliche Unterstützung für Generics innerhalb des Codes des Raw-Typs. Jeder Typparameter wird in seine Löschung umgewandelt (was im obigen Beispiel nur Object
ist).
Ein Raw-Typ ist das Fehlen eines Typ-Parameters bei Verwendung eines generischen Typs.
Raw-Typen sollten nicht verwendet werden, da sie Laufzeitfehler verursachen könnten, z.B. das Einfügen einer double
in das, was ein Set
von int
s sein sollte.
Set set = new HashSet();
set.add(3.45); //ok
Beim Abrufen der Elemente aus dem Set
wissen Sie nicht, was herauskommt. Angenommen, Sie erwarten, dass es alles int
s sind, und Sie wandeln sie in Integer
um; Ausnahme zur Laufzeit, wenn die double
3.45 auftaucht.
Wenn Sie Ihrem Set
einen Typ-Parameter hinzufügen, erhalten Sie sofort einen Kompilierfehler. Dieser vorbeugende Fehler ermöglicht es Ihnen, das Problem zu beheben, bevor während der Laufzeit etwas schief geht (was Zeit und Mühe spart).
Set set = new HashSet();
set.add(3.45); //NICHT ok.
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.
0 Stimmen
Die Java-Tutorials verwenden immer noch das JComboBox, das diese Warnung verursacht. Welche Version des JComboBox wird diese Warnung nicht verursachen? docs.oracle.com/javase/tutorial/uiswing/components/…
5 Stimmen
Beachten Sie, dass es die sogenannten Raw-Typen nur aus Gründen der Rückwärtskompatibilität mit Java 1.4 und älteren Versionen gibt, die überhaupt keine Generics hatten.