In Java hätte ich gerne etwas wie:
class Clazz<T> {
static void doIt(T object) {
// ...
}
}
Aber ich verstehe
Es kann kein statischer Verweis auf den nicht statischen Typ T erstellt werden
Ich verstehe Generika nicht über die grundlegenden Verwendungszwecke hinaus und kann daher nicht viel Sinn daraus machen. Es hilft nicht, dass ich im Internet nicht viele Informationen zu diesem Thema finden konnte.
Könnte jemand auf ähnliche Weise klären, ob eine solche Verwendung möglich ist? Warum war mein ursprünglicher Versuch ebenfalls erfolglos?
quelle
Java weiß nicht, was
T
ist, bis Sie einen Typ instanziieren.Vielleicht können Sie statische Methoden durch Aufrufen ausführen,
Clazz<T>.doit(something)
aber es hört sich so an, als könnten Sie das nicht.Die andere Möglichkeit, mit Dingen umzugehen, besteht darin, den Typparameter in die Methode selbst einzufügen:
Das bringt dir nicht die richtige Einschränkung für U, aber es ist besser als nichts ...
quelle
Ich bin auf dasselbe Problem gestoßen. Ich fand meine Antwort, indem ich den Quellcode für
Collections.sort
im Java-Framework herunterlud . Die Antwort, die ich verwendet habe, war, das<T>
Generikum in die Methode und nicht in die Klassendefinition einzufügen.Das hat also funktioniert:
Nachdem ich die obigen Antworten gelesen hatte, wurde mir klar, dass dies eine akzeptable Alternative wäre, ohne eine generische Klasse zu verwenden:
quelle
T extends XXX
Syntax enthält.Comparable
. Versuchen Sie es<T extends Comparable<? super T>>
stattdessen.Sie können tun, was Sie möchten, indem Sie beim Deklarieren Ihrer
doIt()
Methode die Syntax für generische Methoden verwenden (beachten Sie das Hinzufügen von<T>
zwischenstatic
undvoid
in der Methodensignatur vondoIt()
):Ich habe den Eclipse-Editor dazu gebracht, den obigen Code ohne
Cannot make a static reference to the non-static type T
Fehler zu akzeptieren, und ihn dann auf das folgende Arbeitsprogramm erweitert (komplett mit einem altersgerechten kulturellen Bezug):Was druckt diese Zeilen auf der Konsole, wenn ich es ausführe:
quelle
<T>
maskiert den ersten auf dieselbe Weise wieclass C { int x; C(int x) { ... } }
der Parameterx
das Feld maskiertx
.static <E extends SomeClass> E foo(E input){return input;}
für jede einzelne Methode, wenn ich etwas tun möchte wiestatic <E extends SomeClass>; //static generic type defined only once and reused
static E foo(E input){return input;}
static E bar(E input){return input;}
//...etc...
Ich denke, diese Syntax wurde noch nicht erwähnt (falls Sie eine Methode ohne Argumente wünschen):
Und der Anruf:
Hoffe das hilft jemandem.
quelle
<String>
da es einfach auf das Typargument folgt, weil Sie es einer Variablen zuweisen. Wenn Sie es nicht zuweisen, schließt es einfachObject
.Es ist richtig in dem Fehler erwähnt: Sie keinen statischen Verweis auf nicht-statischen Typ T. Der Grund machen können , ist der Typparameter
T
durch eine des Typargument zB ersetzt werden kannClazz<String>
oderClazz<integer>
etc. Aber statische Felder / Methoden , die von allen nicht geteilt werden -statische Objekte der Klasse.Der folgende Auszug stammt aus dem Dokument :
Wie Chris in seiner Antwort zu Recht betont hat, müssen Sie den Typparameter für die Methode und in diesem Fall nicht für die Klasse verwenden. Sie können es schreiben wie:
quelle
So etwas wie das Folgende würde dich näher bringen
BEARBEITEN: Beispiel mit mehr Details aktualisiert
quelle
Wenn Sie einen generischen Typ für Ihre Klasse angeben, weiß JVM, dass nur eine Instanz Ihrer Klasse vorhanden ist, keine Definition. Jede Definition hat nur einen parametrisierten Typ.
Generika funktionieren wie Vorlagen in C ++, daher sollten Sie zuerst Ihre Klasse instanziieren und dann die Funktion mit dem angegebenen Typ verwenden.
quelle
Clazz<int>::doIt( 5 )
)Einfach ausgedrückt geschieht dies aufgrund der "Erasure" -Eigenschaft der Generika. Dies bedeutet, dass wir zwar definieren
ArrayList<Integer>
undArrayList<String>
zur Kompilierungszeit zwei verschiedene konkrete Typen beibehalten, die JVM jedoch zur Laufzeit generische Typen und löscht Erstellt nur eine ArrayList-Klasse anstelle von zwei Klassen. Wenn wir also eine statische Typmethode oder etwas anderes für ein Generikum definieren, wird sie von allen Instanzen dieses Generikums gemeinsam genutzt. In meinem Beispiel wird sie von beidenArrayList<Integer>
gemeinsam genutzt.ArrayList<String>
Aus diesem Grund wird der Fehler angezeigt. Ein generischer Typparameter einer Klasse ist nicht In einem statischen Kontext erlaubt!quelle
@BD bei Rivenhill: Da diese alte Frage im letzten Jahr erneut Beachtung gefunden hat, lassen Sie uns ein wenig weitermachen, nur um zu diskutieren. Der Körper Ihrer
doIt
Methode macht überhaupt nichtsT
Spezifisches. Hier ist es:Sie können also alle Typvariablen und nur Code vollständig löschen
OK. Aber kommen wir dem ursprünglichen Problem näher. Die erste Typvariable in der Klassendeklaration ist redundant. Es wird nur die zweite Methode benötigt. Jetzt geht es wieder los, aber es ist noch nicht die endgültige Antwort:
Es ist jedoch allzu viel Aufhebens um nichts, da die folgende Version genauso funktioniert. Es wird lediglich der Schnittstellentyp für den Methodenparameter benötigt. Nirgendwo sind Typvariablen in Sicht. War das wirklich das ursprüngliche Problem?
quelle
Da statische Variablen von allen Instanzen der Klasse gemeinsam genutzt werden. Zum Beispiel, wenn Sie folgenden Code haben
T ist erst verfügbar, nachdem eine Instanz erstellt wurde. Statische Methoden können jedoch verwendet werden, noch bevor Instanzen verfügbar sind. Daher können generische Typparameter nicht in statischen Methoden und Variablen referenziert werden
quelle