views:

92

answers:

4

I was going over the tutorials for GWT and was confused by this piece of code.

The code is at GWT tutorials

private void addStock() {
        final String symbol = newSymbolTextBox.getText().toUpperCase().trim();
        newSymbolTextBox.setFocus(true);

        // Stock code must be between 1 and 10 chars that are numbers, letters,
        // or dots.
        if (!symbol.matches("^[0-9A-Z\\.]{1,10}$")) {
            Window.alert("'" + symbol + "' is not a valid symbol.");
            newSymbolTextBox.selectAll();
            return;
        }

        newSymbolTextBox.setText("");

        // Don't add the stock if it's already in the table.
        if (stocks.contains(symbol))
            return;

        // Add the stock to the table.
        int row = stocksFlexTable.getRowCount();
        stocks.add(symbol);
        stocksFlexTable.setText(row, 0, symbol);
        stocksFlexTable.setWidget(row, 2, new Label());
        stocksFlexTable.getCellFormatter().addStyleName(row, 1,
                "watchListNumericColumn");
        stocksFlexTable.getCellFormatter().addStyleName(row, 2,
                "watchListNumericColumn");
        stocksFlexTable.getCellFormatter().addStyleName(row, 3,
                "watchListRemoveColumn");

        // Add a button to remove this stock from the table.
        Button removeStockButton = new Button("x");
        removeStockButton.addStyleDependentName("remove");
        removeStockButton.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                int removedIndex = stocks.indexOf(symbol);
                stocks.remove(removedIndex);
                stocksFlexTable.removeRow(removedIndex + 1);
            }
        });
        stocksFlexTable.setWidget(row, 3, removeStockButton);

        // Get the stock price.
        refreshWatchList();
    }

The problem part is the anonymous inner class to add event handling to the removeStockButton. The class' onClick method accepts an event and then retrieves the index of row-to-be-deleted from the ArrayList stocks using the variable symbol.

How will symbol still be in scope when the user actually calls onClick(), i.e. clicks the remove button? If you doubt the correctness of the code, it's from Google engineers and so is correct (plus, it works, I've used it).

Is this some JavaScript trick or do I need Java referesher courses?

A: 

Note the keyword "final" in the declaration of symbol.

(No & Yes, respectively to your final questions.)

+3  A: 

This is because and only because symbol was declared as final in the enclosing method.

Here's a link to a brief explanation of anonymous classes in Java : see here.

JRL
Technically it would be in scope even if it wasn't `final`, although it wouldn't compile. (The practical difference is that a field of the same name in the outer class would be hidden (is that the right term?).)
Tom Hawtin - tackline
+1  A: 

The language basically takes care of this in the background with a feature called a Closure. The closure binds "symbol" to the class. In order for this to work in Java, the variable must be final (which it is here).

manovi
I find calling this a closure confusing. That's not what closures are in other languages, they're much more than that. I'd keep it at anonymous inner class. But that's just my opinion.
JRL
java anonymous inner classes are a poor man's closure =)
Chii
A: 

Yes, you need to get a refresher on your Java skills. This type of programming is very common in Java. As said by the others: since symbol is final, you can access it from inner classes.

David Nouls