Instanziieren Sie die Java-Lambda-Funktion anhand des Namens

8

Ich möchte in Java 8 eine Lambda-Funktion erstellen, deren Klassennamen holen und sie dann später aus ihrem Klassennamen instanziieren.

Das ist was ich versuche:

%Vor%

Allerdings bekomme ich mit diesem Code (in beiden Varianten unter Verwendung der statischen Methodenreferenz und unter Verwendung des lokal deklarierten Lambda) eine Ausnahme:

%Vor%

Ich hätte erwartet, dass ich die statische Methodenreferenz zumindest re-instantiieren kann ... nein, anscheinend nicht.

Ich habe einen ähnlichen Ansatz mit Groovy Closures verwendet und das hat gut funktioniert. Also mache ich etwas falsch mit den Java 8 Lambda, oder ist es nicht möglich, Lambdas beim Namen zu instanziieren? Ich habe im Netz einige Hinweise gefunden, dass Lambdas serialisiert werden können, also würde ich erwarten, dass es auch möglich sein sollte, sie mit Namen zu instanziieren.

    
rec 20.07.2016, 21:03
quelle

2 Antworten

5

Nun, es ist eine besondere Eigenschaft von JRE / OpenJDK von Oracle, "anonyme Klassen" zu verwenden, auf die überhaupt nicht mit Namen zugegriffen werden kann. Aber auch ohne dies gibt es keinen Grund, warum dies funktionieren sollte:

  • Class.forName(String) versucht, die Klasse über die ClassLoader des Aufrufers aufzulösen. Selbst wenn Lambda-Ausdrücke mit normalen Klassen implementiert wurden, waren sie nicht zugänglich, wenn sie über eine andere ClassLoader geladen wurden.
  • Class.newInstance() funktioniert nur, wenn ein public no-arg-Konstruktor vorhanden ist. Sie können nicht davon ausgehen, dass es einen Nicht-Arg-Konstruktor gibt oder dass es public ist
  • Die Annahme, dass die Logik der gesamten Funktion in einer einzelnen Klasse liegen muss, ist falsch. Ein Gegenbeispiel wäre java.lang.reflect.Proxy , das interface Implementierungen erzeugt, die an eine InvocationHandler delegieren. Der Versuch, einen solchen Proxy über seinen Klassennamen erneut zu instanziieren, würde fehlschlagen, weil Sie die tatsächliche InvocationHandler -Instanz an den Konstruktor des Proxys übergeben müssen. Im Prinzip könnte die JRE-spezifische Lambda-Ausdrucksimplementierung ein ähnliches Muster verwenden

Unter Berücksichtigung der obigen Punkte sollte klar sein, dass man nicht sagen kann, dass es im Allgemeinen mit inneren Klassen gearbeitet hat. Es gibt viele Einschränkungen, die Sie dafür erfüllen müssen.

In Bezug auf die Serialisierung funktioniert es für serialisierbare Lambda-Ausdrücke, weil das persistente Formular vollständig von der Runtime-Implementierungsklasse getrennt ist, wie in beschrieben Antwort Daher ist der Name der generierten Klasse nicht in der serialisierten Form enthalten, und das Deserialisierungsende könnte eine vollständig andere Laufzeitimplementierung haben.

    
Holger 21.07.2016, 08:07
quelle
0

Speichern Sie die Lambda-Instanzen in Map und geben Sie den Instanznamen ein. Sie können die Map über eine Singleton-Wrapper-Klasse global verfügbar machen (achten Sie nur auf Synchronisationsprobleme).

%Vor%     
NickF 20.07.2016 22:20
quelle

Tags und Links