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 переменной из внутренного класса?
/** * 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.