[英]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.