Dieses Papier analysiert die Unterschiede zwischen JDK1.4, JDK1.5 und JDK1.6 in Java -Programmierung in Kombination mit Beispielen. Teilen Sie es für Ihre Referenz wie folgt weiter:
Einfach ausgedrückt: Es gibt zwei größte Unterschiede zwischen 1,4 und 1,5. Eine davon ist, dass 1.5 Generika aufweist und der andere 1.5 automatisch eingekapselte Datentypen von acht grundlegenden Datentypen zusammenfassen kann. Das heißt, Ganzzahl a = 4 ist nicht erlaubt. Es gibt keinen großen Unterschied zwischen 1,5 und 1,6. 1.6 Ich denke, die meisten Änderungen sind die GUI, die eine Menge bequemer Layout -Management und -verlängerung bietet.
In dieser Zeit trat ich einer E-Government-Firma bei und benutzte WebLogic8. Dann verwenden wir JDK1.4. Eclipse hat die JDK -Version geändert. Die vorherigen Projekte sind jedoch im Grunde genommen populär geworden.
★ Neue Funktionen von JDK1.5:
1. Generika
2 Automatische Packung/Unboxing
3 for-lach
4 Statische Import
5 Parameter der variablen Länge
1. Generika (Vermeiden Sie es, Fehler auszuführen, die durch Typguss verursacht werden können)
Zum Beispiel:
ArrayList List = new ArrayList (); list.add (New Integer (3)); list.add (New Integer (4)); int i = ((Integer) (list.get (0))). parseInt ();
Sehr problematisch
ArrayList <Integer> list = new ArrayList <GanzEger> (); list.add (New Integer (3)); list.add (New Integer (4)); int i = list.get (0) .ParSInt ();
2 Automatische Packung/Unboxing
Der letzte Satz des obigen Beispiels kann geändert werden in:
Die Codekopie lautet wie folgt: int i = list.get (0);
Da der ursprüngliche Typ und die entsprechende Wrapper -Klasse nicht explizit konvertiert werden müssen
3 for-lach
Verbesserung von Schleifen
int a [] = {......}; // initialisieren für (int i: a) {......}Verwenden Sie nicht das vorherige i = 0; i <A.Length; i ++
4 Statische Import
Zuvor beunruhigte Java.math
Die Codekopie lautet wie folgt: math.sqrt ();
Jetzt statischer Import Java.lang.math.sqrt;
sqrt ();
Es entspricht dieser Methode in Ihrer eigenen Klasse
5 Parameter der variablen Länge
int sum (int ... intList) {int sum; sum = 0; für (int i = 0; i <intlist.length; i ++) {sum+= intlist [i]; } return sum;}Es gibt einen Parameter, behandeln Sie ihn als Array
★ Neue Funktionen von JDK6.0
Verbesserte für die Schleifenanweisung Annotation Aufzählung von "versteckten" statischen Methodenvariadienparametern (Vararg)
Wildcards und Kovarianzrendite für Schleifenanweisungen verbessert sich
Um über Sets und Arrays zu iterieren, bietet der erweiterte für die Schleife eine einfache, kompatible Syntax. Es gibt zwei erwähnenswerte Punkte:
1. In einer Schleife wird der Initialisierungsausdruck nur einmal berechnet. int Ausdruck
Ungehindert für:
int sum = 0; Integer [] numbers = computerumns (); für (int i = 0; i <number.length; i ++) sum+= number [i];
Erweitert für:
int sum = 0; für (int number: computerumnumbers ()) sum += nummer;
Einschränkung
Iterator oder ein Einweis kann nicht während der Verbesserung für die Schleifen -Iteration zugegriffen werden
Bitte beachten Sie das folgende Beispiel:
für (int i = 0; i <number.length; i ++) {if (i! = 0) system.out.print (","); System.out.print (Nummern [i]);}Hier ist ein weiteres Beispiel:
für (Iterator <Integer> it = n.Iderator (); it.hasnext ();) if (it.Next () <0) it.remove ();
Kommentare
Kommentarverarbeitung ist ein großes Thema. Da sich dieser Artikel nur auf die Kernsprachenmerkmale konzentriert, beabsichtigen wir nicht, all seine möglichen Formen und Fallstricke abzudecken. Wir werden integrierte Annotationen (unterdrückt die Wung, veraltet und außer Kraft gesetzt) und die Einschränkungen der allgemeinen Annotationsverarbeitung diskutieren.
Warnungen unterdrücken
Dieser Kommentar deaktiviert Compiler -Warnungen auf Klasse oder Methode. Manchmal wissen Sie deutlicher als der Compiler, dass der Code eine abgelehnte Methode verwenden muss oder eine Aktion ausführen muss, die nicht statisch feststellen kann, ob Typ-Safe Typ-Safe ist, und verwenden:
@SuppressWarnings ("Abschaltung") öffentlich statische void selfstruct () {thread.currentThread (). Stop ();}Dies ist wahrscheinlich das Nützlichste an eingebauten Anmerkungen. Leider unterstützt Javac für 1.5.0_04 es nicht. Aber 1.6 unterstützt es und Sun arbeitet daran, es rückwärts in 1,5 zu portieren.
Diese Annotation wird in Eclipse 3.1 unterstützt, und andere IDEs können sie auch unterstützen. Auf diese Weise können Sie den Code vollständig von der Warnung freigeben. Wenn es zur Kompilierung zu einer Warnung besteht, können Sie sicher sein, dass Sie ihn nur hinzugefügt haben - um einen unsicheren Code anzuzeigen. Mit der Hinzufügung von Generika wird es nützlicher sein.
Veraltet
Leider ist veraltet nicht so nützlich. Es war ursprünglich beabsichtigt, das @Deprecated Javadoc -Tag zu ersetzen, aber da es keine Felder enthält, gibt es keine Möglichkeit, vorzuschlagen, welche Benutzer von veralteten Klassen oder Methoden als Ersatz verwendet werden sollten. am meisten
Beide Verwendung erfordert das Javadoc -Tag und diese Annotation.
Überschreiben
Override sagt, dass die mit der IT kommentierte Methode Methoden mit derselben Signatur in der Superklasse überschreiben sollte:
@Overridepublic int HashCode () {...}Wenn Sie sich das obige Beispiel ansehen, wenn "C" nicht in HashCode aktiviert ist, wird es zur Kompilierungszeit keine Fehler geben, aber die Methode wird nicht wie erwartet zur Laufzeit genannt. Durch das Hinzufügen des Override -Tags fordert der Compiler auf, wenn er das Umschreiben tatsächlich ausführt.
Dies ist auch in Situationen hilfreich, in denen sich Superklassen ändern. Wenn der Methode ein neuer Parameter hinzugefügt wird und die Methode selbst umbenannt wird, wird die Unterklasse plötzlich nicht kompiliert, da sie nichts mehr aus der Superklasse umschreibt.
Andere Notizen
Kommentare sind in anderen Szenarien sehr nützlich. Wenn nicht das Verhalten direkt geändert wird, sondern das Verhalten, insbesondere beim Hinzufügen von Boilerplate -Code, funktioniert die Annotation in Frameworks wie EJB und Webdiensten sehr gut.
Kommentare können nicht als Präprozessoren verwendet werden. Das Design von Sun verhindert ausdrücklich die Modifikation des Bytecode der Klasse vollständig aufgrund von Kommentaren. Auf diese Weise können Sie die Ergebnisse der Sprache korrekt verstehen, und Tools wie IDE können auch eine detaillierte Codeanalyse und Refactoring durchführen.
Der Kommentar ist keine Silberkugel. Als ich es zum ersten Mal begegnete, versuchten die Leute, verschiedene Techniken auszuprobieren. Bitte beachten Sie die folgenden Vorschläge, die von anderen erhalten wurden:
public class foo {@propertyprivate int bar;}Die Idee ist, automatisch Getter- und Setter -Methoden für die private Feldleiste zu erstellen. Leider gibt es zwei Fehler in dieser Idee: 1) es funktioniert nicht und 2) es macht den Code schwer zu lesen und zu verarbeiten. Es ist unmöglich zu implementieren, denn wie bereits erwähnt, verhindert Sun speziell die Änderung von Klassen mit Kommentaren.
Selbst wenn möglich, ist es keine gute Idee, da der Code den Code schlecht lesbar macht. Wenn Sie diesen Code zum ersten Mal sehen, werden Sie nicht wissen, dass der Kommentar die Methode erstellt. Wenn Sie in Zukunft einige Operationen in diesen Methoden ausführen müssen, sind Kommentare nutzlos. Kurz gesagt, versuchen Sie nicht, Dinge zu tun, die regulärer Code mit Kommentaren ausmachen kann.
aufzählen
Enum ähnelt einer öffentlichen statischen endgültigen INT -Erklärung, die seit vielen Jahren als Enum -Wert verwendet wird. Die größte und offensichtlichste Verbesserung der INT ist die Typensicherheit - Sie können einen anderen Typ nicht fälschlicherweise durch eine Art von Aufzählung ersetzen, die sich von INT unterscheidet, und alle INTs sind für den Compiler gleich. Mit nur sehr wenigen Ausnahmen sollten alle Int-Strukturen im Enum-Stil normalerweise durch Enum-Instanzen ersetzt werden.
Die Aufzählung bietet einige zusätzliche Funktionen. Die beiden praktischen Klassen Enummap und Enumset sind Standard -Set -Implementierungen, die speziell für die Aufzählung optimiert sind. Wenn Sie wissen, dass eine Sammlung nur Enum -Typen enthält, sollten Sie diese speziellen Sammlungen anstelle von HashMap oder Hashset verwenden.
In den meisten Fällen können Sie Enum verwenden, um alle öffentlichen statischen endgültigen INTs im Code zu ersetzen. Sie sind vergleichbar und können statisch importiert werden, daher scheinen Verweise auf sie äquivalent zu sein, selbst für innere Klassen (oder innere Enumentypen). Beachten Sie, dass die Anweisungen, die sie deklarieren, beim Vergleich von Enum -Typen ihre sequentiellen Werte angeben.
"Versteckte" statische Methode
In allen Deklarationen vom Typ Enum werden zwei statische Methoden angezeigt. Da es sich um statische Methoden zu Enum -Unterklassen handelt, nicht auf Methoden der Enum selbst, erscheinen sie nicht in Javadoc von Java.lang.Enum.
Der erste ist Values (), der ein Array aller möglichen Werte des Aufzählungstyps zurückgibt.
Der zweite ist ValueOf (), der einen Enum -Typ für die bereitgestellte Zeichenfolge zurückgibt, die genau mit der Quellcode -Deklaration übereinstimmt.
Verfahren
Einer unserer Lieblingsaspekte bei Enumtypen ist, dass es Methoden haben kann. In der Vergangenheit müssen Sie möglicherweise einen Code schreiben, um die öffentliche statische endgültige INT umzuwandeln und ihn aus dem Datenbanktyp in eine JDBC -URL umzuwandeln. Jetzt kann der Enum -Typ selbst mit einem kompletten gemacht werden
Methoden zum Manipulieren von Code. Hier finden Sie ein Beispiel, einschließlich der abstrakten Methode des Datenbankens -Enum -Typs und der Implementierung, die in jeder Enum -Instanz bereitgestellt wird:
public enum databaSetype {oracle {public String getJdbcurl () {...}}, mysql {public String getJdbcurl () {...}}; public abstract String getJdbcurl ();};Jetzt kann der Enum -Typ seine praktischen Methoden direkt bereitstellen. Zum Beispiel:
Databasetyp DBType = ...; String jdbcurl = dbType.getJdbcurl ();
Um die URL zu erhalten, müssen Sie im Voraus wissen, wo sich die Versorgungsmethode befindet.
Vararg
Durch die korrekte Verwendung von mutablen Parametern werden einige Junk -Code gereinigt. Ein typisches Beispiel ist eine Protokollmethode mit einer variablen Anzahl von Stringparametern:
Log.log (String -Code) log.log (String -Code, String arg) log.log (String -Code, String arg1, String arg2) log.log (String -Code, String [] args)
Wenn Sie variable Parameter diskutieren, ist es interessant, dass, wenn Sie die ersten vier Beispiele durch neue variable Parameter ersetzen, kompatibel ist:
Kopieren Sie den Code wie folgt: log.log (String -Code, Zeichenfolge ... Args).
Alle veränderlichen Parameter sind Quellen kompatibel - wenn alle aufrufenden Programme der Log () -Methode neu kompiliert werden, können alle vier Methoden direkt ersetzt werden. Wenn jedoch die Binärverträglichkeit nach hinten erforderlich ist, müssen die ersten drei Methoden aufgegeben werden. Nur die letzte Methode mit einem String -Array -Parameter entspricht der variadischen Version, sodass sie durch die variadische Version ersetzt werden kann.
Typ Cast
Wenn der Anrufer weiß, welche Art von Parametern verwendet werden sollen, sollten Sie das Typ -Gießen mit veränderlichen Parametern vermeiden. Wenn Sie sich das folgende Beispiel ansehen, ist die erste Hoffnung String und die zweite Hoffnung ist eine Ausnahme:
Log.log (Objekt ... Objekte) {String message = (String) Objekte [0]; if (Objects.length> 1) {Ausnahme e = (Ausnahme) Objekte [1]; // Mach etwas mit der Ausnahme}} Die Methodensignatur sollte wie folgt sein, und die entsprechenden veränderlichen Parameter werden unter Verwendung von String bzw. Ausnahme deklariert:
Die Codekopie lautet wie folgt: log.log (String -Nachricht, Ausnahme E, Objekt ... Objekte) {...}
Verwenden Sie keine variablen Parameter, um das Typsystem zu zerstören. Es kann nur verwendet werden, wenn es stark tippt wird. Für diese Regel ist PrintStream.printf () eine interessante Ausnahme: Es bietet Typinformationen als erstes Argument, damit diese Typen später akzeptiert werden können.
Kovarianz zurück
Die grundlegende Verwendung der kovarianten Rendite besteht darin, das Typ -Casting zu vermeiden, wenn der Rückgabetyp einer Implementierung spezifischer ist als die API. Im folgenden Beispiel gibt es eine Zoo -Schnittstelle, die ein Tierobjekt zurückgibt. Unsere Implementierung gibt ein AnimalImpl -Objekt zurück, aber vor JDK 1.5 muss es erklärt werden, ein Tierobjekt zurückzugeben. :
public interface zoo {public Animal getArimal ();} öffentliche Klasse ZooImpl implementiert Zoo {public Animal getArimal () {return New AnimalImpl ();}}Die Verwendung von kovarianten Renditen ersetzt drei Anti-Muster:
Direkter Feldzugriff. Um API -Einschränkungen zu umgehen, setzen einige Implementierungen Unterklassen direkt in Felder aus:
Kopieren Sie den Code wie folgt: zooimpl._animal
Eine andere Form besteht darin, eine Down -Conversion im Anrufprogramm durchzuführen, da die Implementierung tatsächlich eine bestimmte Unterklasse ist:
Die Codekopie lautet wie folgt: ((AnimalImpl) zooImpl.getanimal ()). ImplMethod ();
Die letzte Form, die ich gesehen habe, ist eine konkrete Methode, die verwendet wird, um Probleme zu vermeiden, die durch eine völlig andere Signatur verursacht werden:
Die Codekopie lautet wie folgt: zooImpl._getanimal ();
Diese drei Modi haben ihre Probleme und Einschränkungen. Entweder ist es nicht ordentlich genug oder es enthält unnötige Implementierungsdetails.
Kovarianz
Der kovariante Rückgabemodus ist sauberer, sicherer und einfach zu warten, und es erfordert keine Typguss oder spezifische Methoden oder Felder:
public An Animal GetAnimal () {return New AnimalImpl (); } Ergebnisse verwenden:
Die Codekopie lautet wie folgt: zooImpl.getanimal (). ImplMethod ();
Generika verwenden
Wir werden über Generika aus zwei Perspektiven lernen: Generika mit Generika und Erstellen von Generika. Wir diskutieren nicht die offensichtliche Verwendung von Liste, Set und Karte. Es reicht aus zu wissen, dass generische Sammlungen leistungsfähig sind und häufig verwendet werden sollten.
Wir werden die Verwendung generischer Methoden und die Methode des Compilers zum Abschluss von Typen diskutieren. Normalerweise geht keine davon schief, aber wenn etwas schief geht, kann die Fehlermeldung sehr verwirrend sein, sodass Sie wissen müssen, wie diese Probleme behoben werden können.
Generische Methoden
Neben generischen Typen führt Java 5 auch generische Methoden ein. In diesem Beispiel von java.util.collections wird eine einzelne Elementliste erstellt. Der Elementtyp der neuen Liste wird basierend auf dem Typ des in der Methode übergebenen Objekts abgeleitet:
Kopieren Sie den Code wie folgt: static <T> List <T> collections.singletonList (T O)
Beispiel Verwendung:
public list <Neger> getListofone () {return collections.singletonList (1);}In der Beispielnutzung passieren wir in einem int. Der Rückgabetyp der Methode lautet also List <Ganzzahl>. Der Compiler färbt sich an die Ganzzahl. Dies unterscheidet sich von generischen Typen, da Sie normalerweise nicht explizit Typparameter angeben müssen.
Dies zeigt auch die Interaktion zwischen Autoboxing und Generika. Der Typ -Parameter muss ein Referenztyp sein: Deshalb erhalten wir List <Gearneger> anstelle von List <int>.
Generische Methoden ohne Parameter
Die Methode für leerlist () wird mit Generika als Typ-Safe-Permutation des Feldes leere_list in java.util.Collections eingeführt:
Kopieren Sie den Code wie folgt: static <T> List <T> collectionss.EmptyList ()
Beispiel Verwendung:
public list <Neger> getNointGegers () {return Collectionss.EmptyList ();}Im Gegensatz zum vorherigen Beispiel enthält diese Methode keine Parameter. Wie schließt der Compiler den Typ von t ab? Grundsätzlich wird versucht, den Parameter einmal zu verwenden. Wenn es nicht funktioniert, versucht es erneut, den Rückgabetyp oder den Zuweisungstyp zu verwenden. In diesem Beispiel ist die Rückgabe die Liste <Gefeger>, so dass T als Ganzzahl abgeleitet wird.
Was passiert, wenn eine generische Methode außerhalb der Return -Anweisung oder Zuweisungserklärung aufgerufen wird? Dann kann der Compiler nicht die zweite Übertragung der Typinferenz durchführen. Im folgenden Beispiel wird LeereList () aus dem Bedingungsoperator aufgerufen:
public list <Neger> getNointGegers () {return x? Sammlungen.EmptyList (): NULL;} Da der Compiler den Rückkehrkontext nicht sehen kann und nicht schließen kann, verlangt er und nimmt Objekt auf. Sie sehen eine Fehlermeldung wie: "Die Liste <Object> kann nicht in die Auflistung von <Gentleger> konvertiert werden."
Um diesen Fehler zu beheben, sollten Typparameter explizit an den Methodenaufruf übergeben werden. Auf diese Weise versucht der Compiler nicht, Typparameter zu schließen und kann das richtige Ergebnis erzielen:
Die Codekopie lautet wie folgt: Rückgabe x? Sammlungen. <Ganzzahl> leerlist (): null;
Ein weiterer Ort, an dem dies oft geschieht, befindet sich in Methodenaufrufen. Wenn eine Methode einen Parameter <String> -Parametern annimmt und die übergebene leere Liste () für diesen Parameter aufrufen muss, ist diese Syntax auch erforderlich.
Außerhalb der Sammlung
Hier sind drei Beispiele für generische Typen, die keine Sammlungen sind, sondern Generika auf neuartige Weise verwenden. Alle drei Beispiele stammen aus Standard -Java -Bibliotheken:
Kopieren Sie den Code wie folgt: Klasse <T>
Die Klasse ist auf dem Klassentyp parametrisiert. Dies ermöglicht es, eine neue Stellung ohne Typ zu konstruieren.
Kopieren Sie den Code wie folgt: Vergleichbar <t>
Vergleichbar wird durch den tatsächlichen Vergleichstyp parametrisiert. Dies bietet eine stärkere Typisierung im Vergleich zu () Aufrufen. Zum Beispiel implementiert String vergleichbare <string>. Das Aufrufen von vergleicheto () auf etwas anderem als String fällt zur Kompilierungszeit fehl.
Kopieren Sie den Code wie folgt: Enum <e erweitert Enum <e >>
Enum wird durch den Enum -Typ parametrisiert. Ein Enum -Typ mit dem Namen Color erweitert Enum <farben>. Die Methode getDeclaringClass () gibt in diesem Beispiel ein Color -Objekt zurück. Es unterscheidet sich von GetClass (), der eine namenlose Klasse zurückgeben kann.
Wildcard
Der komplexeste Teil von Generika ist das Verständnis der Wildcard -Charaktere. Wir werden drei Arten von Wildcards und ihre Verwendung diskutieren.
Lassen Sie uns zunächst verstehen, wie Arrays funktionieren. Sie können einer Zahl [] einen Wert von einer Ganzzahl [] zuweisen. Wenn Sie versuchen, einen Float in die Nummer [] zu schreiben, kann er kompiliert werden, aber er wird zur Laufzeit fehlschlägt und eine ArrayStoreException erscheint:
Integer [] ia = New Integer [5]; Zahl [] na = ia; Na [0] = 0,5; // kompiliert, aber zur Laufzeit fehlschlägt
Wenn Sie versuchen, das Beispiel direkt in ein Generikum umzuwandeln, fällt es zur Kompilierung des Zeitpunkts fehl, da die Zuordnung nicht zulässig ist:
List <Gearner> ilist = new ArrayList <GanzEger> (); List <Nummer> nlist = ilist; // nicht erlaubt wird.add (0,5);
Wenn Sie Generics verwenden, werden Sie nicht auf eine Laufzeitklassencastexception stoßen, solange der Code beim Kompilieren nicht angezeigt wird.
Obergrenze Wildcard
Was wir wollen, ist eine Liste des genauen Elementtyps Unbekannt, das sich von Arrays unterscheidet.
List <Nummer> ist eine Liste, deren Elementtyp die spezifische Typnummer ist.
Liste <? Erweitert Nummer> ist eine Liste des genauen Elementtyps Unbekannt. Es ist eine Zahl oder sein Subtyp.
Obergrenze
Wenn wir das anfängliche Beispiel aktualisieren und den Wert der Liste <? Erweitert die Nummer>, dann ist die Zuordnung jetzt erfolgreich:
LIST <NEGEGER> ILIST = New ArrayList <GanzEger> (); Liste <? erweitert Nummer> nlist = ilist; number n = nlist.get (0); nlist.add (0,5); // nicht erlaubt
Wir können eine Nummer aus der Liste erhalten, da wir sie unabhängig vom genauen Elementtyp der Liste (Float, Ganzzahl oder Nummer) zuweisen können.
Wir können immer noch keine schwimmenden Punkttypen in die Liste einfügen. Dies wird zur Kompilierung der Zeit scheitern, da wir nicht beweisen können, dass dies sicher ist. Wenn wir der Liste schwimmende Punkttypen hinzufügen möchten, wird die anfängliche Sicherheit von ilist untergebracht - sie speichert nur Ganzzahl.
Wildcards geben uns ausdrucksvollere Kraft als Arrays.
Warum Wildcards verwenden?
Im folgenden Beispiel werden Wildcards verwendet, um Typinformationen von Benutzern der API zu verbergen. Intern wird das Set als CustomerImpl gespeichert. Die API -Benutzer wissen nur, dass sie ein Set erhalten, aus dem sie den Kunden lesen können.
Hier sind Wildcards benötigt, da es unmöglich ist, Werte für das Festlegen von <Customer> aus set <CustomerImpl> zuzuweisen:
Public Class CustomerFactory {private set <CusticalImpl> _customers; public set <? erweitert Customer> getCustomers () {return _customers;}}Wildcard und kovariante Rückkehr
Eine weitere häufige Verwendung von Wildcard -Charakteren besteht darin, sie mit kovarianter Rückkehr zu verwenden. Die gleichen Regeln wie Zuweisung können auf kovariante Rücksendungen angewendet werden. Wenn Sie einen spezifischeren generischen Typ in einer umgeschriebenen Methode zurückgeben möchten, muss die deklarierte Methode eine Wildcard verwenden:
public interface numberGenerator {publiclist <? erweitert number> generate ();} öffentliche Klasse Fibonaccigenerator erweitert NumberGenerator {publiclist <Integer> generate () {...}}Wenn Sie ein Array verwenden möchten, kann die Schnittstelle die Nummer [] zurückgeben, während die Implementierung Integer [] zurückgeben kann.
Untergrenze
Was wir sprechen, geht hauptsächlich um die Obergrenze. Es gibt auch eine unteren Grenze. Liste <? Supernummer> ist eine Liste des genauen "Elementtyps" unbekannt, kann aber Mnumber oder der Supertyp der Nummer sein. Es kann sich also um eine Liste <nummer> oder eine Liste <objekt> handeln.
Niedrigere Wildkarten sind weitaus seltener als die oberlimitierten Wildcards, sind jedoch erforderlich, wenn sie benötigt werden.
Unter- und Obergrenze
Liste <? erweitert number> readlist = new ArrayList <Integer> (); Nummer n = readlist.get (0); Liste <? super number> writeList = new ArrayList <Objekt> (); WriteList.Add (New Integer (5));
Die erste ist eine Liste von Zahlen, aus denen gelesen werden kann.
Die zweite ist eine Liste von Zahlen, auf die Sie schreiben können.
Unbegrenzte Wildcard
Schließlich kann der Inhalt einer Liste <?> Liste von irgendeiner Art sein, und es ist fast die gleiche wie die Liste <? erweitert Objekt>. Objekte können jederzeit gelesen werden, aber Inhalte können nicht in die Liste geschrieben werden.
Wildcards in öffentlichen APIs
Kurz gesagt, wie bereits erwähnt, sind Platzhalter sehr wichtig, um die Implementierungsdetails vor dem Anrufer zu verbergen, aber selbst wenn die untere gebundenen Wildkarten schreibgeschützten Zugriff zu bieten scheinen, sind sie aufgrund nicht generischer Methoden wie Entfernung nicht der Fall. Wenn Sie eine wirklich unveränderte Sammlung wünschen, können Sie die Methode auf java.util.collection wie unmodifiablelist () verwenden.
Denken Sie an Platzhalter beim Schreiben von APIs. Im Allgemeinen sollten Sie bei der Übergabe generischer Typen versuchen, Platzhalter zu verwenden. Dadurch können mehr Anrufer auf die API zugreifen.
Durch Empfangsliste <? Erweitert die Nummer> anstelle von Listen <Nummer> kann die folgende Methode von vielen verschiedenen Arten von Listen aufgerufen werden:
Die Codekopie lautet wie folgt: void removenegatives (Liste <? Erweitert Nummer> Liste);
Generische Typen konstruieren
Jetzt werden wir diskutieren, wie wir unsere eigenen generischen Typen konstruieren. Wir werden einige Beispiele zeigen, bei denen die Sicherheit der Typ durch die Verwendung von Generika verbessert werden kann, und wir werden auch einige gemeinsame Probleme bei der Implementierung von Generika -Typen diskutieren.
Sammlungsähnliche Funktionen
Das erste Beispiel einer generischen Klasse ist ein Beispiel für den Sammlungsstil. Das Paar hat zwei Typparameter, und das Feld ist eine Instanz des Typs:
Public Final Class Pair <a, b> {public final a First; öffentliches Finale B -zweiter; öffentliches Paar (A First, B Second) {this.First = First; this.Second = Second;}}Dies ermöglicht es, zwei Elemente aus einer Methode zurückzugeben, ohne eine dedizierte Klasse für jede Kombination von zwei Typen zu schreiben. Eine andere Möglichkeit besteht darin, Objekt [] zurückzugeben, was der Typ ist, der unsicher oder unordentlich ist.
In der folgenden Verwendung geben wir eine Datei und einen Booleschen aus der Methode zurück. Der Client der Methode kann Felder direkt ohne Typ Casting verwenden:
public pair <datei, boolean> getFileandwritestatus (String -Pfad) {// Datei und Statusreturn New Pair <Datei, boolean> (Datei, Status);} Paar <Datei, boolean> result = getFileandWritestatus ("..."); Datei f = result.first; boolean schreibbar = result.second;Außerhalb der Sammlung
Im folgenden Beispiel werden Generika für die zusätzliche Kompilierungszeitsicherheit verwendet. Durch die Parametrisierung der DBFactory -Klasse zum erstellten Peer -Typ zwingen Sie die Werksunterklasse tatsächlich, einen bestimmten Subtyp eines Peer zurückzugeben:
public abstract class dbfactory <t erweitert dbppeer> {geschützte abstrakte t createEmptypeer (); publiclist <t> get (String Constraint) {List <T> Peers = New ArrayList <T> (); // Database MagicReturn Peers;}}Durch die Implementierung von DBFactory <Customer> muss der CustomerFactory einen Kunden von CreateEMPTYPeer () zurückgeben:
Public Class CustomerFactory erweitert dbfactory <custic> {public Customer CreateEMPTYPeer () {return New Customer ();}}Generische Methoden
Unabhängig davon, ob Sie Einschränkungen für generische Typen zwischen den Parametern und zwischen Parametern und Rückgabetypen auferlegen möchten, können Sie generische Methoden verwenden:
Wenn beispielsweise die geschriebene Inversionsfunktion invertiert ist, ist möglicherweise keine generische Methode erforderlich. Wenn Sie jedoch möchten, dass die Inversion eine neue Liste zurückgibt, möchten Sie möglicherweise, dass der Elementtyp der neuen Liste mit dem Typ der eingehenden Liste übereinstimmt. In diesem Fall ist eine generische Methode erforderlich:
Kopieren Sie den Code wie folgt: <t> Liste <T> umgekehrt (Liste <T> Liste).
Beton
Bei der Implementierung einer generischen Klasse möchten Sie möglicherweise ein Array T [] konstruieren. Da Generika durch Löschung implementiert werden, ist dies nicht erlaubt.
Sie können versuchen, Objekt [] zu T [] zu gießen. Aber das ist nicht sicher.
Betonlösungen
Nach der Übereinkommen von generischen Tutorials verwendet die Lösung ein "Typ Token". Durch Hinzufügen eines Klasse <T> zum Konstruktor können Sie den Client dazu zwingen, das richtige Klassenobjekt für die Typ -Parameter der Klasse anzugeben:
public class arrayExample <t> {private class <t> clazz; public arrayExample (class <t> clazz) {this.clazz = clazz;} public t [] getarray (int size) {return (t []) array.newinstance (Clazz, Größe);}}}}}}}}}}}}}}}}}}}}}Um ein ArrayExample <string> zu konstruieren, muss der Client String.class an den Konstruktor übergeben, da der String -Typ.class Class <string> ist.
Wenn Sie ein Klassenobjekt haben, können Sie eine Gruppe eines richtigen Elementtyps konstruieren
Ich hoffe, dieser Artikel wird für Java -Programme aller hilfreich sein.