重写匿名内部类方法不起作用



你能用这种方式覆盖一个方法吗?

public class test {
public static void main(String[] args) throws IOException {        
File dir = new File("M:\Java\Test") {
@Override
public String[] list() { 
String[] listA = super.list();                
for (String s : listA) {
s = "test" + s;
}                
return listA;
}
};
String[] listB = dir.list();
for (String s : listB) {
System.out.println(s);
}
}
}

我期望:

test1.txt
test10.txt
test2.txt
test3.txt
test4.txt
test5.txt
test6.txt
test7.txt
test8.txt
test9.txt

我收到了:

1.txt
10.txt
2.txt
3.txt
4.txt
5.txt
6.txt
7.txt
8.txt
9.txt

我不能问一个新问题,它涉及相同的代码,所以我会在这里问。编译器错误是否由嵌套方法重写引起?

public class test {
public static void main(String[] args) throws IOException {
File dir = new File("M:\Java\Test") {
@Override
public String[] list() {
String[] listA = super.list(new FilenameFilter() {
@Override
public boolean accept(File file, String string) {
return string.contains(".txt");
}
});
for (int i = 0; i < listA.length; i++) {
listA[i] = "test" + listA[i];
}                                
return listA;
}
};
String[] listB = dir.list();
for (String s : listB) {
System.out.println(s);
}
}
}

我收到了:

Exception in thread "main" java.lang.StackOverflowError  
at java.io.File.list(File.java:1155)  
at findmyorder.test$1.list(test.java:22)  
at java.io.File.list(File.java:1155)  
at findmyorder.test$1.list(test.java:22)  
at java.io.File.list(File.java:1155)  
at findmyorder.test$1.list(test.java:22)  
at java.io.File.list(File.java:1155)  
at findmyorder.test$1.list(test.java:22)  
at java.io.File.list(File.java:1155)  
at findmyorder.test$1.list(test.java:22)  
at java.io.File.list(File.java:1155)  
at findmyorder.test$1.list(test.java:22)  
at java.io.File.list(File.java:1155) 

它看起来像一个无限循环。向list()函数添加FilenameFilter后出现问题。 这是嵌套@Override的结果吗?

您返回的是相同的列表。将你的 for 循环替换为:

for(int i=0;i<listA.length;i++)
{
listA[i] = "test" + listA[i];
}

问题出在以下行上:

s = "test" + s;

所做的只是更新s变量。它对列表中的字符串没有任何影响。

相反,使用更新的名称构建一个新数组,并返回该数组。

@Override
public String[] list() { 
String[] listA = super.list();                
String[] listB = new String[listA.length]; // ***
int n = 0;                                 // ***
for (String s : listA) {
listB[n++] = "test" + s;               // ***
}                
return listB;                              // ***
}

旁注:File#list可以返回null

返回:

一个字符串数组,用于命名此抽象路径名表示的目录中的文件和目录。如果目录为空,则数组将为空。如果此抽象路径名不表示目录,或者发生 I/O 错误,则返回null

(我的强调(

。因此,您需要处理这种可能性:

@Override
public String[] list() { 
String[] listA = super.list();                
if (listA == null) {                       // ***
return null;                           // ***
}                                          // ***
String[] listB = new String[listA.length];
int n = 0;
for (String s : listA) {
listB[n++] = "test" + s;
}                
return listB;
}

在这里:

String[] listA = super.list();                
for (String s : listA) {
s = "test" + s;
}                

创建一个新的字符串对象,并将其分配给以前指向数组成员的引用。

然后:

return listA;

返回该数组。

您的代码不会更改数组的内容。迭代数组,为每个条目创建一个新字符串。然后你扔掉这个新字符串,然后返回原始的、未修改的数组。

你可以像这样使用一个衬垫:

return Arrays.stream(super.list()).map(s -> s = "test" + s).toArray(String[]::new);

除此之外,我会非常小心地使用这样的多态性。文件的协定说:此方法返回"子文件"名称。合约没有说:它返回操纵的文件名。因此,对于真正的生产代码使用,我宁愿创建一个实现其"自己的"合约的帮助程序/实用程序类,即:"给我一个文件列表,我以有意义的方式在它们前面加上前缀"。

String[] listA = super.list();                
for (String s : listA) {
s = "test" + s;
}                
return listA;

没有做你所期望的。尝试

for (int i = 0; i < listA.length; i++) {
listA[i] = "test" + listA[i];
}
String

是一个不可变的类,所以s = "test" + s;在这里没有影响。你应该使用这样的东西:

File dir = new File(".") {
@Override
public String[] list() {
String[] listA = super.list();
if (listA != null) {
for (int i = 0; i < listA.length; i++) {
listA[i] = "test" + listA[i];
}
}
return listA;
}
};
String[] listB = dir.list();
if (listB != null) {
for (String s : listB) {
System.out.println(s);
}
}

最新更新