How to get a value from lambda in Java?

If you reached this article, you most likely face one of these errors, and trying to get rid of one, get another: «variable used in lambda expression should be final or effectively final», «variable may be not initialized», «cannot assign a value to final variable».

For my explanation I will use vaadin’s Window.

public class SelectionWindow extends Window {
	private Button okButton = null;
	private BeanItemContainer container;
	private LegalEntity selected;
 
	public SelectionWindow(List items){
	...
		setClosable(false);
		container = new BeanItemContainer<>(Entity.class, items);
		grid = new Grid(container);
		grid.addSelectionListener(event -> {
			Object selectedObj = grid.getSelectedRow();
			selected = (LegalEntity) selectedObj;
			if (okButton != null) {
				okButton.setEnabled(selected != null);
			}
 		});
	}
 
	// the only way to close the window
	public void setOkButtonListener(Button.ClickListener listener) {
        okButton.addClickListener(listener);
    }
 
	// this way we get selected item
	public Entity getSelected() {
        return selected;
    }
 
}

So, to pass params into the Window you just add arguments to the constructor. In my case I don’t need a private field List items. If I did, I would add:

private List items;

and a line to constructor:

this.items = items;

You can use setters as well.

Case 1. You just need to read selected value and to use right in the code of the listener.

SelectionWindow selectionWindow = new SelectionWindow(items);
selectionWindow.setOkButtonListener(clickEvent -> {
    Entity selected = selectionWindow.getSelected();
    populateFromSelection(selected);
    selectionWindow.close();
});
 
private void populateFromSingleSuggestion(LegalEntity legalEntity) {
	// react upon the new value
}

The point is that you know in the code when your Window gets closed. On this event you can read any field/state from it (you can add getters) and update your UI.

Case 2. You want to read a value and assign to a variable with a wider scope. Use atomic reference.

final AtomicReference reference = new AtomicReference<>();
 
selectionWindow.setOkButtonListener(clickEvent -> {
                reference.set(selectionWindow.getSelected());
                selectionWindow.close();
            });

Then get your item with reference.get().

You can leave a response, or trackback from your own site.

Leave a Reply