我需要创建几个按钮并上传文件。所以我想创建一个设置这些按钮的功能。但是,我在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
,因为我想将file
分配给它。
我想知道这个问题是否有任何解决方法。
任何帮助将不胜感激。 :)
感谢@M。普罗霍罗夫和@Chang Liu。 根据{{3}}
使用但未在内部类中声明的任何局部变量,形式参数或异常参数必须声明为final或者是有效的final,否则会在尝试使用时发生编译时错误。
因此,当我尝试在FileSlectionListener
内发送参数file1
时,会出现编译错误。但是,Solution中的成员file
不是局部变量,因此如果从我的方法中删除File
,则不会出现错误。所以@talex的anwser在这种情况下是正确的。
但是,由于我的问题是要找到一种方法将selectedFile
传递给内部类并使用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");
}
}
}
分配变量,我无法找到适合它的方法。我的解决方法是基于@Chang Liu的回答。
我修改后的代码如下:
SimpleTest.obj : error LNK2019: unresolved external symbol "public:
__cdecl SimpleClass::SimpleClass(void)" (??0SimpleClass@@QEAA@XZ) referenced in function "private: void __cdecl SimpleTest::testSimpleClass(void)" (?testSimpleClass@SimpleTest@@AEAAXXZ)
不过,如果你有更好的答案,欢迎给我任何建议。 :)
答案 0 :(得分:2)
您有两个名为file
的变量。一个是类变量,另一个是方法参数。
只需从您的方法中删除参数file
,一切正常。
答案 1 :(得分:0)
您可以为文件创建一个可变的包装类:
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()
来获取最后选择的文件。
答案 2 :(得分:0)
只需将您的动作侦听器提取为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);
}
}
答案 3 :(得分:0)
如M. Prokhorov's comment所述,如果您转到JLS 8.1.3. Inner Classes and Enclosing Instances,您会看到声明:
使用但未在内部类中声明的任何局部变量,形式参数或异常参数必须声明为final或effectively final,否则在尝试使用时会发生编译时错误。
关于变量使用的类似规则适用于lambda表达式的主体。
因此,作为变量的方法File file
的参数setNewButton
在您的内部类new FileSelectionListener
的方法{{1}中不是 effectively final },即你为这个变量分配了一个新值,这使得不 实际上是最终的。
通过为setSelection
定义setter而不是传递参数来解决此编译时错误的一些解决方法(但我不确定这是否是最佳做法):
file