Java « почему в Java нельзя обращаться к не final переменной из внутренного класса?

Есть исходный код:

/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .java.geshi_code {font-family:monospace;} .java.geshi_code .imp {font-weight: bold; color: red;} .java.geshi_code .kw1 {color: #000000; font-weight: bold;} .java.geshi_code .kw2 {color: #000066; font-weight: bold;} .java.geshi_code .kw3 {color: #003399;} .java.geshi_code .kw4 {color: #000066; font-weight: bold;} .java.geshi_code .co1 {color: #666666; font-style: italic;} .java.geshi_code .co2 {color: #006699;} .java.geshi_code .co3 {color: #008000; font-style: italic; font-weight: bold;} .java.geshi_code .coMULTI {color: #666666; font-style: italic;} .java.geshi_code .es0 {color: #000099; font-weight: bold;} .java.geshi_code .br0 {color: #009900;} .java.geshi_code .sy0 {color: #339933;} .java.geshi_code .st0 {color: #0000ff;} .java.geshi_code .nu0 {color: #cc66cc;} .java.geshi_code .me1 {color: #006633;} .java.geshi_code .me2 {color: #006633;} .java.geshi_code span.xtra { display:block; }

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class TextComponentTest
{
    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                TextComponentFrame frame = new TextComponentFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setVisible(true);
            }
        });
    }
}

class TextComponentFrame extends JFrame
{
    public TextComponentFrame()
    {
        setTitle(title);
        setSize(DEFAULT_WIDTH,DEFAULT_HEIGHT);

        final JTextField textField = new JTextField();
        final JPasswordField passwordField = new JPasswordField();
       
        JPanel northPanel = new JPanel();
        northPanel.setLayout(new GridLayout(2,2));
        northPanel.add(new JLabel("Username: ",SwingConstants.RIGHT));
        northPanel.add(textField);
        northPanel.add(new JLabel("Password: ",SwingConstants.RIGHT));
        northPanel.add(passwordField);
        add(northPanel,BorderLayout.NORTH);

        final JTextArea textArea = new JTextArea(8,40);
        JScrollPane scrollPane = new JScrollPane(textArea);
        add(scrollPane,BorderLayout.CENTER);

        JPanel southPanel = new JPanel();
        JButton insertButton = new JButton("Insert");
        southPanel.add(insertButton);
        insertButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent event)
            {
                textArea.append("Username: "+textField.getText()+" " + "Password: "+new String(passwordField.getPassword())+"n");
            }
        });
        add(southPanel,BorderLayout.SOUTH);
    }
    private String title = "Auth";
    private int DEFAULT_WIDTH = 250;
    private int DEFAULT_HEIGHT = 350;
}
 



если убрать из кода final, к примеру в этих местах
/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .java.geshi_code {font-family:monospace;} .java.geshi_code .imp {font-weight: bold; color: red;} .java.geshi_code .kw1 {color: #000000; font-weight: bold;} .java.geshi_code .kw2 {color: #000066; font-weight: bold;} .java.geshi_code .kw3 {color: #003399;} .java.geshi_code .kw4 {color: #000066; font-weight: bold;} .java.geshi_code .co1 {color: #666666; font-style: italic;} .java.geshi_code .co2 {color: #006699;} .java.geshi_code .co3 {color: #008000; font-style: italic; font-weight: bold;} .java.geshi_code .coMULTI {color: #666666; font-style: italic;} .java.geshi_code .es0 {color: #000099; font-weight: bold;} .java.geshi_code .br0 {color: #009900;} .java.geshi_code .sy0 {color: #339933;} .java.geshi_code .st0 {color: #0000ff;} .java.geshi_code .nu0 {color: #cc66cc;} .java.geshi_code .me1 {color: #006633;} .java.geshi_code .me2 {color: #006633;} .java.geshi_code span.xtra { display:block; }

final JTextField textField = new JTextField();
final JPasswordField passwordField = new JPasswordField();
 


то компилятор начнет ругаться:

local variable textField is accessed from within inner class; needs to be declared final
local variable passwordField is accessed from within inner class; needs to be declared final
 


Собственно, почему в Java нельзя обращаться к не final переменной из внутренного класса?

1 ответов


Мне, как .NET разработчику, понравился вопрос. Решил посмотреть, что есть в спецификациях.
final в данном случае требуется, поскольку происходит замыкание (closure) на эту переменную. Скорее всего, разработчики Java закрывают часть проблем, сопутствующих реализации замыканий в языке.

UPDATE: Вопрос на StackOverflow http://stackoverflow.com/questions/3910324/why-inner-classes-require-final-outer-instance-variables-java.