[英]Java - access to variable within inner class or assign a value to final variable
我需要创建几个按钮并上传文件。 所以我想创建一个函数来设置这些按钮。 但是,我的setNewButton
内部出现编译错误。
我的代码如下所示:
public class Solution extends JFrame {
private static final String FILE_NAME_1 = "my file1";
private File file1;
private void setNewButton(Container contentPane, final String fileName, String format, File file) {
contentPane.add(Box.createVerticalStrut(5));
final Label label = new Label("Select " + fileName + " in ." + format +" format");
contentPane.add(label);
contentPane.add(Box.createVerticalStrut(10));
Button selection = new Button("Select " + fileName);
contentPane.add(selection);
selection.addActionListener(new FileSelectionListener("Only " + format + " is allowed", format) {
@Override
protected void setSelection(File selectedFile) {
file = selectedFile; // compilation error here
label.setText("Selected" + fileName + selectedFile.getAbsolutePath());
}
});
}
public uploadFiles() {
Container contentPane = this.getContentPane();
setNewButton(contentPane, FILE_NAME_1, "xls", file1);
}
}
错误是: Variable file is accessed from within inner class, needs to be declared final
我在stackoverflow中检查了一些类似的问题。 我知道file
必须像这里的label
和fileName
是最终的。
但是这里的file
可能是final
因为我想将selectedFile
分配给它。
我想知道是否有任何解决此问题的方法。
任何帮助,将不胜感激。 :)
感谢@M。 Prokhorov和@Chang Liu。 根据JLS 8.1.3。 内部类和封闭实例
任何在内部类中使用但未声明的局部变量,形式参数或异常参数都必须声明为final或有效地声明为final,否则在尝试使用时会发生编译时错误。
因此,当我尝试在FileSlectionListener
内部发送参数file
,将出现编译错误。 但是,解决方案中的成员file1
不是局部变量,因此,如果我从方法中删除file
,则不会有错误。 因此,@ talex的答案正确。
但是,由于我的问题是找到一种将File
传递给内部类并使用selectedFile
分配变量的方法,所以我找不到解决方法。 我的解决方法基于@Chang Liu的答案。
我修改后的代码如下:
public class Solution extends JFrame {
private static final String FILE_NAME_1 = "my file1";
private File file1;
private void setNewButton(Container contentPane, final String fileName, String format) {
contentPane.add(Box.createVerticalStrut(5));
final Label label = new Label("Select " + fileName + " in ." + format +" format");
contentPane.add(label);
contentPane.add(Box.createVerticalStrut(10));
Button selection = new Button("Select " + fileName);
contentPane.add(selection);
selection.addActionListener(new FileSelectionListener("Only " + format + " is allowed", format) {
@Override
protected void setSelection(File selectedFile) {
setFile(selectedFile, fileName); // no compilation error here
label.setText("Selected" + fileName + selectedFile.getAbsolutePath());
}
});
}
public uploadFiles() {
Container contentPane = this.getContentPane();
setNewButton(contentPane, FILE_NAME_1, "xls", file1);
}
private void setFile(File file, String fileName) {
switch (fileName) {
case FILE_NAME_1:
sollFile = file;
break;
default:
throw new AssertionError("Unknown File");
}
}
}
不过,如果您有更好的答案,欢迎给我任何建议。 :)
您的名称file
有两个变量。 一个是类变量,另一个是方法参数。
只需从您的方法中删除参数file
,一切都将正常工作。
您可以为文件创建一个可变的包装器类:
public class FileWrapper {
/** The file. */
private File file;
public File getFile() {
return file;
}
public void setFile(File file) {
this.file = file;
}
}
然后,您可以使用该类的最终实例:
final private FileWrapper fileWrapper = new FileWrapper();
// ...
selection.addActionListener(new FileSelectionListener("Only " + format + " is allowed", format) {
@Override
protected void setSelection(File selectedFile) {
fileWrapper.setFile(selectedFile);
label.setText("Selected" + fileName + selectedFile.getAbsolutePath());
}
});
并通过在内部类外部调用fileWrapper.getFile()
获得最后选择的文件。
只需将您的动作侦听器提取为名称为Solution的内部类,就可以从内部类中分配Solution.this.file:
public class Solution extends JFrame {
private class MyListener extends FileSelectionListener{
@Override
protected void setSelection(File selectedFile) {
Solution.this.file = selectedFile; // NO compilation error here
}
}
private static final String FILE_NAME_1 = "Selected SOLL:";
private File file;
private void setNewButton(Container contentPane, final String fileName, String format, File file) {
contentPane.add(Box.createVerticalStrut(5));
final Label label = new Label("Select " + fileName + " in ." + format +" format");
contentPane.add(label);
contentPane.add(Box.createVerticalStrut(10));
Button selection = new Button("Select " + fileName);
contentPane.add(selection);
selection.addActionListener(new MyListener() );
}
public uploadFiles() {
Container contentPane = this.getContentPane();
setNewButton(contentPane, FILE_NAME_1, "xls", file1);
}
}
如M.Prokhorov的评论所述 ,如果您转到JLS 8.1.3。 内部类和封闭实例 ,您将看到以下内容:
使用但未在内部类中声明的任何局部变量,形式参数或异常参数必须声明为final或有效地为final ,否则在尝试使用时会发生编译时错误。
关于变量使用的类似规则适用于lambda表达式的主体。
因此,在您的内部类new FileSelectionListener
的方法setSelection
,方法setNewButton
的参数File file
作为变量没有有效地最终 new FileSelectionListener
,即,您为该变量分配了新值,这使其实际上没有 最终确定 。
通过为file
定义setter而不是传递参数来解决此编译时错误的一些解决方法(但我不确定这是否是最佳实践):
public class Solution extends JFrame {
private static final String FILE_NAME_1 = "Selected SOLL:";
private File file;
private void setNewButton(Container contentPane, final String fileName, String format) {
contentPane.add(Box.createVerticalStrut(5));
final Label label = new Label("Select " + fileName + " in ." + format +" format");
contentPane.add(label);
contentPane.add(Box.createVerticalStrut(10));
Button selection = new Button("Select " + fileName);
contentPane.add(selection);
selection.addActionListener(new FileSelectionListener("Only " + format + " is allowed", format) {
@Override
protected void setSelection(File selectedFile) {
setFile(selectedFile); // call file setter here
label.setText("Selected" + fileName + selectedFile.getAbsolutePath());
}
});
}
// define a setter for your File member
private void setFile(File file) {
this.file = file;
}
public void uploadFiles() {
Container contentPane = this.getContentPane();
setNewButton(contentPane, FILE_NAME_1, "xls");
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.