Kann die Methodenreferenz in MethodHandle konvertiert werden?

9

Ist es möglich, eine Methodenreferenz (z. B. SomeClass::someMethod ) in eine MethodHandle -Instanz zu konvertieren? Ich möchte die Vorteile der Kompilierzeitprüfung (die sicherstellen, dass die Klasse und Methode vorhanden ist) sowie die Möglichkeit, die Methode mit der MethodHandle API zu überprüfen.

Anwendungsfall: Ich habe Code, der genau dann ausgeführt werden muss, wenn die Anfrage nicht von einer bestimmten Methode ausgelöst wurde (um eine endlose Rekursion zu vermeiden). Ich möchte eine Kompilierzeitprüfung, um sicherzustellen, dass die Klasse / Methode existiert, aber eine Laufzeitprüfung, um den Aufrufer mit der Methode zu vergleichen.

Zur Erinnerung: Ist es möglich, einen Methodenverweis in ein MethodHandle umzuwandeln?

    
Gili 30.10.2014, 09:34
quelle

1 Antwort

4

Nun, wenn Sie sich die zusätzlichen Kosten und Sicherheitsaspekte leisten können, können Sie ein Serializable funktional interface verwenden und die serialisierte Form der Methodenreferenzinstanz dekodieren, um das Ziel zu finden, wie in diese Antwort oder wieder mit diese Frage und ihre Antworten aufgekommen ist .

Sie sollten jedoch Ihr Software-Design wirklich überdenken. "Endlose Rekursion vermeiden" sollte nicht durch Dekodieren irgendeiner Art von Parameterobjekt behoben werden, insbesondere nicht, wenn angenommen wird, dass dieser tatsächliche Argumentwert den Aufrufer Ihrer Methode darstellt. Wie würdest du jemals diese seltsame Beziehung erzwingen?

Selbst eine einfache Codeänderung wie das Verweisen auf eine Methode, die an die andere Methode delegiert wird, würde Ihre Prüfung unterbrechen. Hier ist ein einfaches Beispiel, das die subtilen Probleme mit Ihrem Ansatz zeigt:

%Vor%

Wenn Sie dieses Programm ausführen, wird etwas wie folgt gedruckt:

%Vor%

zeigt, dass die Methodenreferenz in der generierten Instanz nicht die erwartete SimpleTest::process ist, sondern stattdessen SimpleTest::lambda$MR$main$process$a9318f35 , die schließlich process aufruft. Der Grund ist, dass einige Operationen (hier varargs -Verarbeitung) nicht von der generierten interface -Instanz ausgeführt werden, sondern stattdessen von einer synthetischen Methode, so wie Sie run((a,b)-> SimpleTest.process(a,b)) geschrieben haben. Der einzige Unterschied ist der Name der synthetischen Methode.

Sie sollten keine Software entwerfen, die sich auf solch fragile Selbstbeobachtung stützt. Wenn Sie die Rekursion vermeiden möchten, genügt ein einfacher ThreadLocal -Flag, der angibt, ob Sie sich bereits in Ihrer spezifischen Methode befinden. Aber es könnte sich lohnen, sich selbst zu fragen, warum Ihre API überhaupt eine endlose Rekursion provoziert; es scheint etwas grundsätzlich falsch zu sein ...

    
Holger 30.10.2014 15:21
quelle