Was ist ein raw-type und warum sollten wir das nicht nutzen?
Fragen:
- Was sind raw-Typen in Java, und warum ich oft zu hören, dass Sie nicht verwendet werden sollte im neuen code?
- Was ist die alternative, wenn wir nicht verwenden können raw-Typen, und wie geht es besser?
die java-tutorials verwenden noch die JComboBox, die Ursachen dieser Warnung. Welche version der combobox wird nicht dazu führen, diese Warnung ? docs.oracle.com/javase/tutorial/uiswing/components/...
Beachten Sie, dass der Grund, warum raw-Typen gibt, ist für die Abwärtskompatibilität zu Java 1.4 und ältere, die nicht die Generika überhaupt.
Beachten Sie, dass der Grund, warum raw-Typen gibt, ist für die Abwärtskompatibilität zu Java 1.4 und ältere, die nicht die Generika überhaupt.
InformationsquelleAutor polygenelubricants | 2010-05-05
Du musst angemeldet sein, um einen Kommentar abzugeben.
Was ist ein raw-Typ?
The Java Language Specification definiert ein raw-Typ wie folgt:
JLS 4.8 Raw-Typen
Hier ein Beispiel zur Veranschaulichung:
Hier
MyType<E>
ist ein parametrisierten Typ (JLS 4.5). Es ist üblich, in der Umgangssprache beziehen sich auf diese Art als einfachMyType
für die kurze, aber technisch gesehen ist der nameMyType<E>
.mt
hat ein raw-Typ (und erzeugt Compilerwarnung) durch den ersten Punkt in der obigen definition;inn
hat auch eine raw-Typ durch den Dritten Punkt.MyType.Nested
ist nicht ein parametrisierter Typ ist, obwohl er ein Mitglied der Typ von einem parametrisierten TypMyType<E>
, weil esstatic
.mt1
, undmt2
sind beide erklärte mit den tatsächlichen Typ-Parameter, also sind Sie nicht raw-Typen.Was ist so besonders an der raw-Typen?
Im wesentlichen raw-Typen verhält sich genau so, wie Sie waren, bevor generics eingeführt wurden. Das heißt, das folgende ist völlig legal zur compile-Zeit.
Der obige code läuft Prima, aber nehmen wir an, Sie haben auch die folgenden:
Jetzt laufen wir in Probleme zur Laufzeit, weil
names
enthält etwas, das nicht eininstanceof String
.Vermutlich, wenn Sie wollen
names
enthalten nurString
Sie könnte vielleicht immer noch mit einem rohen Art und manuell überprüfen, jedenadd
sich selbst, und dann manuell cast zuString
jedes Element ausnames
. Noch besser, ist aber NICHT mit einem raw-Typ und lass den compiler die ganze Arbeit für Sie, die Nutzung der macht von Java generics.Natürlich, wenn Sie TUN wollen
names
zu ermöglichenBoolean
, dann können Sie deklarieren es alsList<Object> names
, und würde der obige code kompiliert.Siehe auch
Wie ein raw-Typ unterscheidet sich von dem verwenden
<Object>
als Typ-Parameter?Das folgende ist ein Zitat aus Effektive Java, 2nd Edition, Artikel 23: keine raw-Typen im neuen code:
Um den Punkt zu illustrieren, betrachten die folgende Methode, die eine
List<Object>
und fügt einnew Object()
.Generics in Java invariant. Ein
List<String>
ist nicht einList<Object>
, also Folgendes erzeugen würde eine compiler-Warnung:Wenn Sie erklärt hatte, dass
appendNewObject
zu nehmen, ein raw-TypList
als parameter, dann wird diese zusammenstellen würde, und man würde Sie verlieren deshalb die Art der Sicherheit, die Sie von Generika.Siehe auch
<E extends Number>
und<Number>
?Wie ein raw-Typ unterscheidet sich von dem verwenden
<?>
als Typ-parameter?List<Object>
,List<String>
usw sind alleList<?>
ist, so kann es verlockend sein, einfach nur zu sagen, dass Sie nurList
statt. Es gibt jedoch einen wichtigen Unterschied: da eineList<E>
definiert nuradd(E)
, Sie können nicht fügen Sie einfach jedes beliebige Objekt zu einemList<?>
. Auf der anderen Seite, da der raw-TypList
nicht haben, geben Sicherheit, Sie könnenadd
nur über alles, was zu einemList
.Betrachten Sie die folgende Variante des vorhergehenden Codeausschnitt:
Den compiler haben eine wunderbare Arbeit und schützt Sie vor potenziell Verletzung der Typ Invarianz der
List<?>
! Wenn Sie erklärt hatte, dass die parameter der raw-TypList list
, dann würde der code kompilieren, und Sie würden gegen die Typ-Invarianten vonList<String> names
.Ein raw type ist die Löschung von dieser Art
Zurück zu JLS 4.8:
In einfacheren Worten, wenn ein raw-Typ verwendet wird, werden die Konstruktoren, Methoden einer Instanz und nicht-
static
Felder sind auch gelöscht.Nehmen Sie das folgende Beispiel:
Wenn wir den raw -
MyType
,getNames
wird gelöscht, so dass es gibt ein raw -List
!JLS 4.6 weiterhin erklären die folgenden:
Den folgenden bug-report enthält einige Gedanken von Maurizio Cimadamore, einen compiler dev, und Alex Buckley, einer der Autoren der JLS, über das warum diese Art von Verhalten sollte auftreten: https://bugs.openjdk.java.net/browse/JDK-6400189. (Kurz gesagt, es macht die Spezifikation einfacher.)
Wenn es unsicher ist, warum ist es erlaubt, ein raw-Typ?
Hier ist ein weiteres Zitat von JLS 4.8:
Effektive Java 2nd Edition auch noch diese hinzufügen:
In der Zusammenfassung, raw-Typen sollten NIE benutzt werden, in die der neue code. Sie sollten immer die Verwendung von parametrisierten Typen.
Gibt es keine Ausnahmen?
Leider, weil die Java-generics sind nicht-verdinglicht, es gibt zwei Ausnahmen, bei denen raw-Typen verwendet werden muss, in die der neue code:
List.class
, nichtList<String>.class
instanceof
Operanden, z.B.o instanceof Set
, nichto instanceof Set<String>
Siehe auch
Collection<String>.class
Illegal?Für die zweite Ausnahme, die syntax
o instanceof Set<?>
ist auch zulässig, um zu vermeiden, die raw-Typ (obwohl es nur oberflächlich in diesem Fall).Raw-Typen sind sehr nützlich und verringern, boilerplate code im Falle des JNDI-lookups für ein bean, welches eine Schnittstelle erweitert. Dies löst das Bedürfnis zu schreiben
n
remote-Bohnen, die für jede implementierende Klasse mit dem identischen code."Nicht-verdinglicht" ist eine andere Art zu sagen, dass Sie gelöscht werden. Der compiler weiß, was der generische Parameter sind, aber diese information ist nicht an den generierten bytecode. Die Justiz, Freiheit und Sicherheit erfordert, dass class-Literale haben keinen Typ-Parameter.
Das ist interessant. Ich meine offiziell ist es weder, weil eine Klasse literal definiert als nur
TypeName.class
, woTypeName
ist eine einfache Bezeichner (jls). Reden wir mal rein hypothetisch, ich denke, es könnte wirklich sein. Vielleicht als Anhaltspunkt,List<String>.class
ist die Variante, dass der JLS fordert insbesondere einen compiler-Fehler, so dass, wenn Sie jemals hinzufügen, um die Sprache, die ich erwarten würde, das ist die, die Sie verwenden.InformationsquelleAutor polygenelubricants
Raw-Arten sind in der alten Geschichte der Sprache Java. Am Anfang gab es
Collections
und hielt SieObjects
nichts mehr und nichts weniger. Jeder Vorgang aufCollections
erforderlichen Abgüsse vonObject
auf den gewünschten Typ.Während diese arbeitete die meiste Zeit, Fehler geschehen
Den alten typeless Sammlungen konnten nicht durchsetzen, Typ-Sicherheit, so die Programmierer hatten sich zu erinnern, was er in einer Sammlung gespeichert.
Generika wo erfunden, um dieses Problem zu umgehen, die Entwickler erklären würde, die gespeicherten Typ hat und der compiler würde es tun, anstatt.
Zum Vergleich:
Komplexer das Compareable-interface:
Beachten Sie, dass es unmöglich ist, zu implementieren, die
CompareAble
SchnittstellecompareTo(MyCompareAble)
mit raw-Typen.Warum Sie nicht verwenden sollten Sie:
Object
gespeichertCollection
muss gewirkt werden, bevor es verwendet werden kannObject
Was der compiler macht:
Generika sind rückwärts-kompatibel, Sie verwenden die gleichen java-Klassen als die raw-Typen. Die Magie geschieht meist zur compile-Zeit.
Kompiliert werden wie:
Dies ist der gleiche code, den Sie schreiben würden, wenn Sie die raw-Typen direkt. Dachte, ich bin nicht sicher, was passiert mit den
CompareAble
Schnittstelle, ich denke, das es schafft, die zweicompareTo
Funktionen, wobei eineMyCompareAble
und die anderen nehmen eineObject
und der übergabe an den ersten nach dem Gießen.Was sind die alternativen zu raw-Typen: Verwenden Sie Generika
InformationsquelleAutor josefx
Einem raw-type ist der name einer generischen Klasse oder interface ohne Typ-Argumente. Zum Beispiel, angesichts der generischen Klasse Box:
Zum erstellen eines parametrisierten Typ von
Box<T>
liefern Sie eine tatsächliche typargument für den formalen Typ-parameterT
:Wenn der tatsächliche Typ-argument weggelassen wird, erstellen Sie eine rohe Art von
Box<T>
:Daher
Box
ist der raw-type des generischen TypsBox<T>
. Jedoch, eine nicht-generische Klasse oder ein interface ist nicht ein raw-Typ.Raw-Typen zeigen, bis in legacy-code, da viele API-Klassen (wie z.B. die Collections-Klassen) wurden nicht generisch vor JDK 5.0. Bei der Verwendung von raw types, Sie im wesentlichen erhalten pre-Generika-Verhalten — eine
Box
gibt SieObject
s. Für die Abwärtskompatibilität, die Zuweisung eines parametrisierten Typ an seine roh geben darf:Aber wenn Sie zuweisen eine raw-Typ, um einen parametrisierten Typ, erhalten Sie eine Warnung:
Erhalten Sie auch eine Warnung, wenn Sie ein raw geben Sie zum aufrufen von generischen Methoden definiert, die in den entsprechenden generischen Typ:
Die Warnung zeigt, dass die raw-Typen umgehen generischen Typ prüft, verzögern den Fang von unsicherem code zur Laufzeit. Daher sollten Sie vermeiden, mit raw-Typen.
Dem Typ Erasure Abschnitt hat mehr Informationen darüber, wie der Java-compiler verwendet raw-Typen.
Deaktiviert Fehlermeldungen
Wie bereits erwähnt, beim mischen von legacy code mit generischen code, stoßen Sie möglicherweise Warnmeldungen ähnlich der folgenden:
Dies kann passieren, wenn eine ältere API, die arbeitet auf raw-Typen, wie im folgenden Beispiel gezeigt:
Der Begriff "deaktiviert" bedeutet, dass der compiler nicht genügend Informationen geben, um alle typüberprüfungen notwendig, um sicherzustellen, geben Sicherheit. Die "unchecked" - Warnung ist deaktiviert, standardmäßig, aber der compiler gibt einen Hinweis. Um zu sehen, alle "unchecked" - Warnungen, recompile with-Xlint:unchecked.
Neukompilierung des vorherigen Beispiels mit -Xlint:unchecked zeigt die folgenden zusätzlichen Informationen:
Komplett deaktivieren deaktiviert Warnungen, verwenden Sie den-Xlint:-ungeprüfter Flagge. Die
@SuppressWarnings("unchecked")
annotation unterdrückt unchecked-Warnungen. Wenn Sie nicht vertraut sind mit der@SuppressWarnings
syntax, siehe Anmerkungen.Original-Quelle: Java Tutorials
InformationsquelleAutor Adelin
Sollten Sie die Typ-parameter.
Die Warnung weist darauf hin, dass Arten, die definiert sind, unterstützen Generika sollte parametrisiert werden, anstatt mit Ihrer rohen form.
List
definiert ist, zur Unterstützung von generics:public class List<E>
. Dadurch können viele Typ-sichere Operationen, überprüft werden compile-Zeit.private static List<String> list = new ArrayList<>();
InformationsquelleAutor Bozho
Einem "raw" - Datentyp in Java ist eine Klasse, die nicht-generische und beschäftigt sich mit dem "roh" - Objekte, sondern als typsichere generische Typ-Parameter.
Beispielsweise vor den Java-generics zur Verfügung, die Sie verwenden würden, eine collection-Klasse so:
Wenn Sie fügen Sie Ihre Objekt auf der Liste, es ist nicht egal, welche Art von Objekt es sich handelt, und, wenn man es von der Liste, müssen Sie explizit casten auf den Typ, den Sie erwarten.
Die Verwendung von Generika, entfernen Sie das "unbekannte" Faktor, da müssen Sie explizit angeben, welche Art von Objekten kann in der Liste:
Beachten Sie, dass mit Generika, die Sie nicht haben, um CASTET das Objekt aus der get-Aufruf, die Sammlung ist bereits definiert, nur mit MyObject. Diese Tatsache ist der wichtigste treibende Faktor für Generika. Es ändert sich eine Quelle von runtime-Fehlern, die in etwas, das kann überprüft werden bei der Kompilierung.
ähnlich, aber anders! Mit
?
bietet noch geben Sicherheit. Ich deckte es in meiner Antwort.InformationsquelleAutor Andy White
Der compiler will Sie, dies zu schreiben:
weil sonst, könnte man hinzufügen, jede Art, die Sie gerne in
list
, so dass die Instanziierung alsnew ArrayList<String>()
sinnlos. Java generics sind eine compile-Zeit-Funktion nur, so ein Objekt erstellt mitnew ArrayList<String>()
gerne akzeptierenInteger
oderJFrame
Elemente bei der Zuweisung zu einer Referenz der "raw type"List
- das Objekt selbst weiß nichts über das, was Arten ist es enthalten soll, nur der compiler ist.InformationsquelleAutor Michael Borgwardt
Was ist ein raw-type und warum ich oft zu hören, dass Sie nicht verwendet werden sollte im neuen code?
Einem "raw-type" ist die Verwendung einer generischen Klasse ohne Angabe eines argument type(s) für den parametrisierten Typ(en), z.B. mit
List
stattList<String>
. Wenn generics wurden in Java mehrere Klassen aktualisiert wurden, verwenden Generika. Die Verwendung dieser Klasse wie ein "raw type" (ohne Angabe eines Typ-argument) erlaubt, legacy-code noch kompilieren."Raw types" verwendet werden, für die rückwärts Kompatibilität. Ihre neue code wird nicht empfohlen, da durch die Verwendung der generischen Klasse mit einem typargument ermöglicht eine stärkere Typisierung, was wiederum verbessern die code-Verständlichkeit und führen zu fangen potenzielle Probleme früher.
Was ist die alternative, wenn wir nicht verwenden können raw-Typen, und wie geht es besser?
Der am günstigsten gelegene alternative ist die Verwendung von generischen Klassen wie vorgesehen - mit einem geeigneten argument Typ (z.B.
List<String>
). Dies ermöglicht es dem Programmierer, um die Angabe von Typen genauer gesagt, vermittelt mehr Bedeutung für zukünftige maintainer über den Verwendungszweck einer variable oder Datenstruktur, und es ermöglicht dem compiler zu erzwingen, besser Typ-Sicherheit. Diese Vorteile zusammen können der Verbesserung der code-Qualität und verhindern, dass die Einführung von einige coding Fehler.Beispielsweise für eine Methode, wenn der Programmierer will, um sicherzustellen, eine Liste variable namens 'Namen' enthält nur Zeichenfolgen:
polygenelubricants
's "raw type" Referenzen von stackoverflow.com/questions/2770111/... in meiner eigenen Antwort, aber ich Schätze, ich werde lassen Sie Sie für die Verwendung in seine/Ihre eigene Antwort.ja, ich habe im wesentlichen das kopieren-und-einfügen das segment, wo die Leute verwenden des raw-Typen auf stackoverflow, und schließlich beschlossen, nur noch eine Frage zu verweisen, um von nun an. Ich hoffe, es ist ein guter Beitrag für die Gemeinschaft.
Ich bemerkte - wir schlagen einige die gleichen Fragen 🙂
In der Tat. Im Allgemeinen präzise und einfache Antworten sind mindestens so gut wie die lange und akzeptierte.
InformationsquelleAutor Bert F
Hier bin ich Angesichts mehrerer Fälle, durch die Sie clearify das Konzept
Fall 1
ArrayList<String> arr
es ist einArrayList
Referenz-variable mit Typ -String
dem Verweis auf eineArralyList
Objekt vom TypString
. Es bedeutet, es kann halt nur Typ Zeichenfolge-Objekt.Ist es eine Streng zu
String
nicht ein Raw-Typ, so, Es wird nie auslösen einer Warnung .Fall 2
In diesem Fall
ArrayList<String> arr
ist ein strenger Typ, aber Ihr Objektnew ArrayList();
ist ein raw-Typ.hier
arr
ist ein Strenger Typ. So, Es wird zu erhöhen compile-Zeit-Fehler beim hinzufügen einesinteger
.Fall 3
In diesem Fall
ArrayList arr
ist ein raw-Typ, aber Ihr Objektnew ArrayList<String>();
ist ein Strenger Typ.Wird es fügen Sie jede Art von Objekt hinein, weil
arr
ist ein Raw-Typ.InformationsquelleAutor Vikrant Kashyap
Einen raw-Typ ist die fehlende type-parameter bei der Verwendung von generischen Typen.
Raw-Typ sollte nicht verwendet werden, da könnte es zu einem Laufzeitfehler führen, wie das einsetzen einer
double
in das, was sein sollte, war einSet
vonint
s.Beim abrufen der Stoff, aus dem
Set
Sie nicht wissen, was da raus kommt. Nehmen wir an, dass Sie erwarten, dass es alleint
s, sind Sie Gießen esInteger
; exception zur Laufzeit, wenn diedouble
3.45 kommt.Mit einem type-parameter Hinzugefügt, um Ihre
Set
erhalten Sie einen compile-Fehler auf einmal. Diese preemptive Fehler können Sie beheben das problem, bevor etwas explodiert während der Laufzeit (und damit die Einsparung von Zeit und Aufwand).InformationsquelleAutor Lars Andren
Hier ist ein weiterer Fall, wo raw-Typen wird dich beißen:
Als erwähnt wurde, sind in der akzeptierten Antwort, verlieren Sie alle Unterstützung für Generika in den code der raw-Typ. Jeder Typ-parameter umgewandelt, deren Löschung verlangen (die im obigen Beispiel ist nur
Object
).InformationsquelleAutor GuyPaddock
Was sagt, ist, dass Ihre
list
ist einList
von unespecified Objekte. Das ist, dass Java nicht weiß, welche Art von Gegenständen sind in der Liste. Dann, wenn Sie Durchlaufen die Liste, die Sie haben zu werfen jedes element, um Zugriff auf die Eigenschaften des Elements (in diesem Fall String).Im Allgemeinen ist es eine bessere Idee einstellen, die Sammlungen, so dass Sie nicht haben, Konvertierung Probleme auftreten, werden Sie nur in der Lage sein, um Elemente hinzuzufügen oder Elemente der parametrisierten Typ und Ihrem editor bieten Ihnen auch den passenden Methoden zu wählen.
InformationsquelleAutor pakore
tutorial-Seite.
Einem raw-type ist der name einer generischen Klasse oder interface ohne Typ-Argumente. Zum Beispiel, angesichts der generischen Klasse Box:
Zum erstellen eines parametrisierten Typ Box, die Sie liefern, eine tatsächliche typargument für den formalen Typ-parameter T:
Wenn der tatsächliche Typ-argument weggelassen wird, erstellen Sie ein raw-type von Box:
InformationsquelleAutor Mykhaylo Adamovych
Ich diese Seite gefunden nachdem ich einige Beispiel-übungen und mit der exakt gleichen Verwirrung.
============== Ich ging aus dieser code-wie bieten von der Probe ===============
====================== Dieser code ========================
===============================================================================
Es ist möglicherweise sicherer, aber dauerte 4 Stunden demuddle der Philosophie...
InformationsquelleAutor user2442615
Raw-Arten sind in Ordnung, wenn Sie Ausdrücken, was Sie Ausdrücken wollen.
Beispielsweise eine deserialisation Funktion zurückgeben könnte ein
List
ist, aber es nicht wissen, die Liste der element-Typ. SoList
ist der entsprechende Rückgabetyp hier.Ja, aber das ist mehr zu geben und ich bin gegen Eingabe mehr. 🙂
InformationsquelleAutor Stefan Reich
Vermeiden Sie raw-types
Zum Beispiel,
Einer Liste ist ein raw-Typ, während
List<String>
ist ein parametrisierter Typ.Wenn Generika eingeführt wurden in JDK 1.5, raw-Typen wurden beibehalten, nur um die Abwärtskompatibilität mit älteren Versionen von Java. Obwohl die Verwendung von raw types ist immer noch möglich,
Sie vermieden werden sollten,:
Sind Sie weniger ausdrucksstark, und nicht selbst-Dokument in der gleichen Weise wie die parametrisierten Typen
Beispiel
Referenz: https://docs.oracle.com/javase/tutorial/java/generics/rawTypes.html
InformationsquelleAutor ashish