Wie kann ich über einen generischen Platzhalter iterieren? Grundsätzlich möchte ich folgende Methode inline einbinden:
%Vor% Wenn dieser Code wie gezeigt in einer separaten Methode ist, funktioniert er, weil der generische Methodenkontext die Definition eines Platzhaltertyps (hier T
) erlaubt, über den man iterieren kann. Wenn man versucht, diese Methode zu inline zu schreiben, ist der Methodenkontext weg und man kann nicht mehr über einen Platzhaltertyp iterieren. Selbst wenn dies in Eclipse automatisch ausgeführt wird, schlägt der folgende (nicht kompilierbare) Code fehl:
Meine Frage ist einfach: Gibt es eine Möglichkeit, einen Wildcard-Typ zu verwenden, über den man iterieren kann, oder ist dies eine Beschränkung von Generika (was bedeutet, dass dies unmöglich ist)?
Typparameter können nur auf
definiert werdenSie würden einen Typparameter für einen lokalen Block benötigen, was nicht möglich ist.
Ja, manchmal habe ich sowas auch vermisst.
Aber es gibt nicht wirklich ein Problem, wenn die Methode hier nicht-inlined ist - wenn es einen Leistungsengpass darstellt, bei dem Inlining helfen würde, wird Hotspot es wieder einbinden (ohne sich um den Typ zu kümmern).
Wenn Sie eine separate Methode verwenden, können Sie ihr einen aussagekräftigen Namen geben.
Nur eine Idee, wenn Sie das oft brauchen:
%Vor%Nein. In einer solchen Situation besteht die Problemumgehung darin, eine Hilfsmethode zu erstellen.
Die JLS hat dieses Beispiel Ссылка
%Vor% Das Problem ist, wir haben ein Objekt List<?>
. Wir wissen, dass es ein List<X>
von einigen X
sein muss, und wir möchten Code mit X
schreiben. Intern konvertiert der Compiler den Platzhalter in eine Typvariable X
, aber die Programmiersprache Java bietet Programmierern keine direkte Möglichkeit, darauf zuzugreifen. Wenn es jedoch eine Methode gibt, die List<T>
akzeptiert, können wir das Objekt an die Methode übergeben. Der Compiler gibt an, dass T=X
und der Aufruf gut ist.
Wenn es keinen Typ löscht, kann X
zur Laufzeit bekannt sein, dann würde Java uns definitiv einen Weg geben, auf X
zuzugreifen. Seit heute, da X
zur Laufzeit nicht verfügbar ist, hat das wenig Sinn. Es könnte eine rein synthetische Methode bereitgestellt werden, die wahrscheinlich nicht einfacher ist als die Umgehungsmethode der Hilfsmethode.
Sie können immer auf Object
Dies unterliegt natürlich der tatsächlichen Erklärung von doSomething
.
Wenn doSomething
als diese void doSomething( T fact )
deklariert ist, dann wäre es hier ratsam, einen rohen Typ und schlucke unchecked
Warnungen zu verwenden. Wenn Sie garantieren können, dass FactManager
nur homogene Facts
eingefügt haben kann, dann ist das möglicherweise eine OK-Lösung.
Nun, ich kann mir einen Weg vorstellen, wie man innere Klassen verwenden kann, weil die innere Klasse den Typparameter mit seinem einschließenden Typ teilt. Selbst mit Platzhaltern können Sie Ihre Sammlungen dank der Wildcard-Capture-Konvertierung weiterhin verarbeiten.
Lassen Sie mich ein Beispiel erstellen. Dieser Code wird kompiliert und läuft gut. Aber ich kann nicht sicher sein, ob der Gebrauch innerer Klassen für dich ein Problem sein würde.
%Vor%Dies ist genauer auf die von Ihnen definierte Methode abgestimmt (das heißt, wenn Sie iterateFacts () mit den FactManagern in factManagers aufrufen können, wissen Sie, dass der FactManager Elemente enthält, die eine Unterklasse von Fact sind).
%Vor%Ich würde jedoch eher annehmen, dass Sie FactManager als generisch für Untertypen von Fact deklarieren würden (nur mit dem Namen der Klasse), z. B.
%Vor% Das Eclipse-Refactoring schlägt fehl, weil es den Typ eines Objekts, das in FactManager<?>
enthalten ist, nicht ableiten kann.