Wird im Konstruktor safe ein Verweis auf eine überschreibbare Methode verwendet? [Duplikat]

8

Wenn ich einen Ereignis-Listener mit einem Lambda hinzufüge, der eine überschreibbare Methode im Konstruktor aufruft, erhalte ich eine Warnung. Wenn ich eine Methodenreferenz verwende, bekomme ich keine Warnungen über überschreibbare Methoden oder lecke dies. Sollte ich Methodenverweise im Konstruktor vermeiden oder ist es sicher?

Hier ist ein einfaches Beispiel:

%Vor%     
Dave Wolfe 01.07.2014, 18:27
quelle

2 Antworten

6

Methodenreferenzen und Lambdas bewerten beide dasselbe, eine funktionale Schnittstelle:

Also, die zwei sind im Wesentlichen gleichwertig. Im Fall der Methodenreferenz ist das Ziel explizit this und im Fall von Lambda ist es implizit this . Ihre "warnende" ist also die gleiche. Die nächste Frage ist: Wem hat der Compiler falsch geraten? Ist die Warnung falsch oder fehlt eine Warnung?

Der Grund für die Warnung ist, dass das Lecken von this aus dem Konstruktor einige große Gefahren birgt. Einer bezieht sich auf Multithreading: jede Speichersichtbarkeit, die Sie von% co_de erhalten% Feld Semantik (sowie einige andere Garantien) sind weg, wenn Sie final von der Referenz auslaufen lassen. Die andere Sorge ist, dass die this -Methode sofort die Methode auf addListener aufruft, bevor der Konstruktor fertig ist. Das heißt, es wird eine Methode für ein teilweise konstruiertes Objekt aufgerufen. Das ist besonders problematisch für überschreibbare Methoden, weil es sein kann, dass dieser Konstruktor für die Oberklasse einer anderen Person ist und dass jemand anderes die betreffende Methode überschrieben hat. In diesem Fall rufen Sie die Methode für diese Unterklasse auf, deren Konstruktor noch nicht einmal gestartet werden konnte (da der Konstruktor einer Oberklasse zuerst ausgeführt wird).

Also, ja, die Warnung auf dem Lambda ist richtig. Und es sollte auch für die Methodenreferenz da sein.

    
yshavit 01.07.2014, 18:42
quelle
8

Nein, das ist definitiv nicht sicher. Sie veröffentlichen this , auf das der fremde Code zugreifen kann, bevor das Objekt vollständig erstellt wurde. Das Registrieren eines Listeners von einem Konstruktor ist immer ein No-No, ob Sie es über eine anonyme Klasse oder über einen Lambda oder eine Methodenreferenz tun. Ihr Beispiel entspricht dem Idiom, vor dem ich vor 12 Jahren gewarnt habe: Ссылка

Die Einbeziehung von Methodenreferenzen ist hier ein Ablenkungsmanöver; Das Problem besteht darin, dass Sie einen Verweis auf ein teilweise konstruiertes Objekt für Code bereitstellen, den Sie nicht steuern.

Der Compiler kann Sie nicht vor allem warnen; Nur weil es keine Warnung gibt, heißt das nicht, dass Ihr Code richtig ist:)

    
Brian Goetz 01.07.2014 18:52
quelle

Tags und Links