2015-11-05 16 views
5

Così ho preso una classemetodo Java di riferimento getta NPE

public class MenuBar extends JMenuBar { 

    MenuBarController controller; 

    public MenuBar() { 
     JMenu menu = new JMenu("File"); 
     menu.add(createMenuItem("Report", controller::writeReport)); 
     menu.add(createMenuItem("Save", controller::save)); 
     menu.add(createMenuItem("Import", controller::importFile)); 
     menu.add(createMenuItem("Clear DB", controller::clearDatabase)); 
     add(menu); 
    } 

    public void setController(MenuBarController controller) { 
     this.controller = controller; 
    } 
} 

MenuBarController è un'interfaccia la cui attuazione è impostato tramite setController dopo la MenuBar ist creato. Il codice genera una NullpointerException a menu.add(createMenuItem("Report", controller::writeReport)) che può essere causata solo da controller::writeReport. Se sostituisco questo con un lambda come () -> controller.writeReport() non viene lanciato alcun NPE.

1. Perché controller::writeReport lancia un NPE?

2. Perché la lambda non lancia un NPE?

La parte divertente è: Se sostituisco il lambda con il riferimento al metodo usato in precedenza, dopo averlo eseguito una volta con lambda, non vengono più lanciati NPE.

Qualcuno ha idea del perché possa essere? Qualche stranezza javac/eclissi?

+0

Qual è lo stack di chiamate di NPE? Cos'è esattamente null? – Arkadiy

+2

questa segnalazione di bug sembra rilevante: https://bugs.openjdk.java.net/browse/JDK-8131323 – DHall

+5

'controller :: writeReport lancia un NPE?' Perché 'controller' è nullo. Stai provando a fare riferimento a un metodo su un oggetto nullo -> NPE. – njzk2

risposta

3

controller::writeReport genera un valore NPE perché controller è nullo quando viene valutata la linea.

() -> controller.writeReport() non lancia un NPE perché quando viene eseguito il lambda, è stato assegnato un valore a controller.

+2

Questo è più ovvio se si scrive il lambda come '() -> this.controller.writeReport()', con un ricevitore esplicito (che è ciò che significa lambda comunque). Quindi diventa più facile vedere che lambda sta catturando 'this', non' controller', motivo per cui i due si comportano in modo diverso. –

Problemi correlati