【问题标题】:Why does java.io.File.listFiles() throw NPE instead of proper Exception?为什么 java.io.File.listFiles() 抛出 NPE 而不是正确的异常?
【发布时间】:2013-01-11 19:06:08
【问题描述】:

今天我写了一个小的 Java 程序来查找我的硬盘上的文件,部分原因是 Windows 缺少一个合适的程序,部分原因是它是为了好玩。它只是遍历目录的所有子目录,如果它们是目录,则递归遍历所有子目录。但后来我有一个NullPointerException。经过System.out.println()'stry-catch block之后,我发现这发生在D:\System Volume InformationC:\Users\Public\Documents\My VideosC:\ProgramData\Templates 等一些目录上。 Windows 本身说,当在资源管理器地址栏中输入“拒绝访问”时。当探索时,它们似乎被锁定了。来自java.io.Filesource 告诉我:

public File[] listFiles() {
    String[] ss = list();
    if (ss == null) return null; //This line seems to cause the NPE
    int n = ss.length;
    File[] fs = new File[n];
    for (int i = 0; i < n; i++) {
        fs[i] = new File(ss[i], this);
    }
    return fs;
}

我的问题是,为什么没有合适的说法,IOExceptionSecurityException,甚至是IDontCareWhatKindOfExceptionButPleaseNoNullPointerExceptionException

我知道我可以只用try-catchNPEs,或者检查null,但我真的很好奇为什么没有正确的Exception 抛出。

由于我不喜欢 try/catch 并检查 null 是因为代码的审美价值,所以我做了一些讨厌的、讨厌的反射代码(有很多虚伪的 try/catch 块),它模仿了 java.io.File 的一些方法,因为它们是私有的,并且某些包(如java.io.FileSystem)是不可见的。而且因为我不关心某些 Windows 文件,所以我只是使用此代码忽略它们,给我一个空的array

public static File[] listFiles(File mThis) {
    String[] ss = list(mThis);
    if (ss == null) {
        //System.out.println("ss is null");
        return new File[] {};
    }
    int n = ss.length;
    File[] fs = new File[n];
    for (int i = 0; i < n; i++) {
        fs[i] = getNewFile(ss[i], mThis);
    }
    return fs;
}

编辑:为避免误解:我确实使用try/catch,我只是在美学上不喜欢它们。

EDIT2:我宁愿使用 GUI 而不是命令提示符。而且我非常不喜欢 Windows 搜索 GUI。使用起来几乎是痛苦的。

【问题讨论】:

  • 你没听说过find 命令吗?
  • @Woot4Moo 命令行没有合适的 GUI。我更喜欢 GUI。
  • 编写一个 GUI 并以这种方式调用它?只是说微软解决了在系统上查找文件的问题,只是想知道它在 GUI 之外有什么缺点。
  • @ChristiaandeJong 如果您使用 Java 7,请忘记 File,使用 Files。至少那里的 API 是健全的——例如,它会在删除失败时抛出异常,File.delete() 不会!

标签: java file exception nullpointerexception


【解决方案1】:

简答:

  • 安装 JDK 7;
  • 使用新的Files API。

在那之后你永远不会回到File

【讨论】:

  • 至少你提供了一些有用的帮助,而不是指出我的错误。谢谢。
  • 哦,这并不是你真的有错......但是你有没有想过为什么有这么多处理File对象的API/实用程序类(例如,commons-io )?它只是包装 API 并抛出异常;)
【解决方案2】:

之所以如此,是因为API的设计者在函数的合约(文档+签名)中正确识别了原因:

如果这个抽象路径名不代表一个目录,那么这个 方法返回 null。否则返回一个 File 对象数组, 一个用于目录中的每个文件或目录。路径名表示 目录本身和目录的父目录不是 包含在结果中。每个生成的抽象路径名是 使用 File(File, String) 从这个抽象路径名构造 构造函数。因此,如果这个路径名是绝对的,那么每个 结果路径名是绝对的;如果这个路径名是相对的,那么每个 生成的路径名将相对于同一目录。

它返回 null 并给出具体原因。

因为我不喜欢 try/catch 和检查 null 因为 代码的审美价值

这可能是 API 的“缺点”,但您公然无视它,因此您的程序崩溃了。

【讨论】:

  • "如果此抽象路径名不表示目录,则此方法返回 null。"它确实表示一个目录,只是一个不可访问的目录。你从我的问题中引用的那句话被误解了。我确实使用它们,但我不喜欢它们。
  • @ChristiaandeJong 它没有被错误引用,它是用来强化你对 API 的无视 :)。
  • 但是第一部分呢?它确实表示一个目录,只是一个不可访问的目录。所以从技术上讲,我并没有像你所说的那样“公然无视”任何事情。
  • @Woot4Moo 你真的认真地尝试和操作过这个 API 吗?我在 Windows 上遇到过 .canRead() 返回 true 的情况,当尝试在其上打开流时,我得到了 IOException... 因为文件一开始就可读。是的,File 甚至对你撒谎。 Files,从我目前的测试来看,没有。
  • @Woot4Moo 那么,我想知道你为什么要试图捍卫File ;) 至于“如果你没有权限查看/访问某些东西而不是它不存在你”,这是错误的:我可以完美地ls -d 一个我无法读取其内容的目录......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-04-17
  • 2010-12-09
  • 2016-09-01
  • 2012-11-18
  • 2014-06-22
  • 1970-01-01
相关资源
最近更新 更多