820 Stimmen

Was ist ein Rohdatentyp und warum sollten wir ihn nicht verwenden?

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?

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.

18voto

Bert F Punkte 81431

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

1 Stimmen

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.

1 Stimmen

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.

1 Stimmen

@polygenelubricants Ich habe bemerkt - wir haben einige der gleichen Fragen getroffen :-)

15voto

Vikrant Kashyap Punkte 5760

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();

Fall 1

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

Fall 2

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.

Fall 3

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.

0 Stimmen

Im Fall 2, gibt es außer der Warnung noch andere Nachteile? Ich meine, wenn ich die Warnung ignoriere, sind Fall 1 und Fall 2 dann nicht dasselbe...

14voto

Michael Borgwardt Punkte 334642

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.

14voto

GuyPaddock Punkte 1577

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).

9voto

Lars Andren Punkte 8263

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 ints 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 ints 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.com

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.

Powered by:

X