Search code examples
javamultithreadingswinginner-classesfinal

Local variables referred from inner class must be final or effectively final


Please have a look at the below code

private void displayInitialRevenue_Method() {
    //Get the dates from the combo
    String selectedCouple = revenueYearCombo.getSelectedItem().toString();
    if (selectedCouple.equals("Select Year")) {
        return;
    }
    String[] split = selectedCouple.split("/");
    //Related to DB
    double totalAmount = 0.0;
    //Get data from the database
    dbConnector = new DBHandler();
    dbConnector.makeConnection();
    DefaultTableModel model = (DefaultTableModel) initialRevenueTable.getModel();
    model.setRowCount(0);
    ResultSet selectAllDetails = dbConnector.selectAllDetails("SQL CODE ");
    try {
        if (selectAllDetails.isBeforeFirst() == false) {
            JOptionPane.showMessageDialog(null, "This table is empty");
        } else {
            while (selectAllDetails.next()) {
                String clientName = selectAllDetails.getString("Client Name");
                String providerName = selectAllDetails.getString("Provider Name");
                Double amountInvested = selectAllDetails.getDouble("Invest_Amount");
                //Update the table
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        Object[] row = {clientName, providerName, amountInvested};
                        model.addRow(row);
                    }
                });
                //Get the total
                totalAmount = totalAmount + amountInvested;
            }
            //Add the sum
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    Object[] blankRow = {null};
                    model.addRow(blankRow);
                    Object[] row = {totalAmount};
                    model.addRow(row);

                }
            });
        }
    } catch (SQLException sql) {
        JOptionPane.showMessageDialog(null, sql.getLocalizedMessage());
    }
}

This entire method is running inside another thread. The UI updates are running inside SwingUtilities.InvokeLater(). However pls put attention to the below.

Object[]row = {totalAmount};
model.addRow(row);

The variable totalAmount is not final and it cannot be final because it need to be calculated in the above while loop. Since it is not final I am unable to use it inside the SwingUtilities.InvokeLater() as the error says Local variables referred from inner class must be final or effectively final


Solution

  • You can make an additional variable that is Final and then copy the final result of the calculation into it.

    while (selectAllDetails.next()) {
                String clientName = selectAllDetails.getString("Client Name");
                String providerName = selectAllDetails.getString("Provider Name");
                Double amountInvested = selectAllDetails.getDouble("Invest_Amount");
                //Update the table
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        Object[] row = {clientName, providerName, amountInvested};
                        model.addRow(row);
                    }
                });
                //Get the total
                totalAmount = totalAmount + amountInvested;
            }
    final Double totalAmountInvested = totalAmount; // and now use this one in the Inner