覆盖匿名内部 class 方法不起作用

The overriding of anonymous internal class methods does not work

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

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.WhosebugError  
        at java.io.File.list(File.java:1155)  
        at findmyorder.test.list(test.java:22)  
        at java.io.File.list(File.java:1155)  
        at findmyorder.test.list(test.java:22)  
        at java.io.File.list(File.java:1155)  
        at findmyorder.test.list(test.java:22)  
        at java.io.File.list(File.java:1155)  
        at findmyorder.test.list(test.java:22)  
        at java.io.File.list(File.java:1155)  
        at findmyorder.test.list(test.java:22)  
        at java.io.File.list(File.java:1155)  
        at findmyorder.test.list(test.java:22)  
        at java.io.File.list(File.java:1155) 

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

您返回的是同一个列表。用这个替换你的 for 循环:

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

这里:

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

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

然后:

 return listA;

你return那个数组

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

你可以像下面这样:

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

除此之外,我会非常小心地使用这样的多态性。文件的合同说:此方法 return 是 "child file" 名称。合同没有说:它 returns 操纵文件名。因此,对于实际的生产代码使用,我宁愿创建一个 helper/utilities class 来实现其 "own" 合同,即:"give me a list of files, and I prepend them in a meaningful way with a prefix".

这个

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];
}

这一行有问题:

s = "test" + s;

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

相反,使用更新后的名称构建一个新数组,然后return。

@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 可以 return null:

Returns:

An array of strings naming the files and directories in the directory denoted by this abstract pathname. The array will be empty if the directory is empty. Returns null if this abstract pathname does not denote a directory, or if an I/O error occurs.

(我的重点)

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

@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 是不可变的 class,所以 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);
  }
}