【问题标题】:java dereferencing possible null pointerjava取消引用可能的空指针
【发布时间】:2015-11-05 04:00:47
【问题描述】:

在我的代码中,我收到了上述警告。这是我得到它的代码部分,

try {
        fileFile = new File(Main.class.getProtectionDomain().getCodeSource().getLocation().toURI());
    } catch (URISyntaxException | NullPointerException e) {
    }
    finally {
        if (fileFile.getPath()!= null){
            strPathName = fileFile.getPath();
        }
        if (fileFile.getName() != null){
            strFileName = fileFile.getName();
        }
    }  

if (fileFile.getPath()!= null){ 行是带有警告的行。 此代码不是 Main 类的一部分。它在同一个包的另一个类文件中的另一个类中。

我对编程不是很有经验,但我相信我几乎做了所有事情来防止或捕获空指针异常。为什么我仍然得到它,我能做些什么来摆脱它?感谢您的帮助。

在阅读了您的所有提示后,我解决了它。完整代码如下:

public static ArrayList<String> getCurrentPath() {

    File fileFile;
    String strPathName, strFileName;
    ArrayList<String> arrPathFileName;

    strFileName = null;
    strPathName = null;

    try {
        fileFile = new File(Main.class.getProtectionDomain().getCodeSource().getLocation().toURI());
        if (fileFile.getPath()!= null){
            strPathName = fileFile.getPath();
        }
        if (fileFile.getName() != null){
            strFileName = fileFile.getName();
        }
    } catch (URISyntaxException use) {
    }     
    arrPathFileName = new ArrayList<>(); 
    arrPathFileName.add(strPathName);
    arrPathFileName.add(strFileName);

    return arrPathFileName;
}

如前所述,我只是将 if 语句放入 try 块并删除 finally 块。

顺便说一句,还尝试将两个 if 块合并为一种方式:

if (fileFile != null){
            strPathName = fileFile.getPath();
            strFileName = fileFile.getName();
        }

但这会产生一个警告,即 fileFile 永远不会变为 null。 (从一开始我的观点是什么,所以警告“取消引用可能的空指针”真的让我很困惑。)

【问题讨论】:

  • catch (URISyntaxException | NullPointerException e) {}??? -- 永远不要这样做 x 2. 认真的。您是 1) 试图捕获一个永远不应该完成的 NPE - 可能具有这些的代码是损坏的代码并且需要修复,并且 2) 您忽略了 catch 块。请尽快阅读异常处理。
  • 1. `catch (URISyntaxException | NullPointerException e) {}' 是 Netbeans 在我为每个异常设置单独的 catch 子句时所建议的。
  • 这与 NetBeans 没有任何关系,并且再次与 1) NEVER 捕获 NullPointerExceptions,以及 2) NEVER 忽略带有空的异常catch 块(有一些例外)。我坚持我之前的建议:立即阅读有关异常的教程。
  • 1) 我完全同意,程序代码永远不会导致 NPE。这就是为什么我为 NPE 添加了一个额外的 catch 块,Netbeans 建议将它与 URISyntaxException catch 块结合使用,但我的主要目标是以不会发生 NPE 的方式编写代码。 2)你是对的,当仔细考虑时,很明显我添加到 finally 块中的内容使 catchblock 无用。我在 catch 块中有一个 printStackTrace 命令。但 Netbeans 再次建议将其删除。谢谢你的评论。这是朝着正确方向迈出的一小步。
  • @Mike NetBeans 可能建议将这两个 catch-blocks 组合起来,因为它们没有做任何不同的事情。此外,在没有NullPointerExceptions 的情况下,捕获NullPointerException 不是编写代码的正确方法(从外观上我可以看出你可能只是试图修复警告)。

标签: java null


【解决方案1】:

因此,如果您在第一行抛出异常,您的变量将不会被分配给File,并且会保留它的先前值(null,如果之前没有分配)。您的异常被捕获,然后您继续使用该未分配的变量。因此发出警告。请参阅下面的注释代码。

try {
        fileFile = // exception thrown. Variable not assigned
} catch (URISyntaxException | NullPointerException e) {
        // exception caught
    }
    finally {
       // unassigned variable used here...
        if (fileFile.getPath()!= null){
            strPathName = fileFile.getPath();
        }
        if (fileFile.getName() != null){
            strFileName = fileFile.getName();
        }
    }  

如果可行的话,我宁愿在 try 块中限定和使用变量。在您的 finally 块中,您需要尽可能小心,因为您可以从 try 块中的大多数地方来到它。

顺便说一句:

Main.class.getProtectionDomain().getCodeSource().getLocation().toURI();

如果您确实获得了 NPE,将会给您带来巨大的问题。以上哪个解决了 null ?我可能会更明确一点,这样您就可以检查每次调用的空值,并明确地确定哪个调用给了您空值。累吗?不幸的是。

【讨论】:

  • 让我像往常一样挑剔:"unassigned" 是正确的术语吗?由于它要么是一个字段并使用null 初始化,要么是一个局部变量,因此已经分配到其他地方,因此此时不能“取消分配”它。但正如我所说,只是吹毛求疵:D。
  • 我同意你的观点。我最初写的是“未初始化”,然后替换为“未分配”
  • @Brian 我从来没有真正得到过 NPE,只是警告,代码总是编译并运行良好,没有错误。我将 if 语句移到 try 块中,删除了 finally 块,警告现在消失了。感谢您的帮助。
  • @Brian 和 Tom fileFile 实际上是在方法开头的声明块中声明的,只是声明,没有初始化。所以你在代码中看到的是fileFile的第一次使用和初始化。差不多 30 年前,当我学习一些编程基础知识时,Turbo Pascal 是最先进的。所以我仍然遵循 Pascal 的要求 - 程序/函数等开头的声明块,其中必须声明程序/函数等中使用的所有变量,并在可能的情况下进行初始化。从我的角度来看,它使阅读代码更容易一些。
【解决方案2】:

“空指针取消引用”是计算机用空值调用方法的说法。稍微复杂一点,但你说你是新手,所以我想保持简单。

我们来看一个例子:

String s = null;
s = s.toUpperCase();

这是一个关于什么是空指针取消引用的简单示例。 s 是一个空引用(它的值为空),当我们取消引用时(获取它的值)我们有null,当我们在null 上调用toUpperCase() 时,出现了可怕的错误,因为null根本没有任何方法! Java 会抛出一个 NullPointerException 来具体说明。


现在,回到你的代码,因为 fileFile 是在 try 块中分配的,我假设它在它之前被设置为 null 以避免 Java 对未初始化的变量大喊大叫。 (这一切都很好且正确。)在这个 try-block 中,如果您的 catch-block 发生任何异常,它将停止 try-block(意味着 fileFile 不会获得新值,这意味着它仍然是空)。

现在您会注意到警告是 可能 空指针取消引用。这意味着它不一定是null,但可能是! (在我上面的示例中,它始终是一个用于比较的空指针取消引用。)具体来说,如果catch 捕获一个异常,它将为空。

需要明确的是,问题是这样的: fileFile.getPath()。这就像说它可能是null.getPath(),恶心。看起来你试图避免空指针问题,你应该做的是if (fileFile != null) {然后在 if 里面做你想做的事。


另外,因为您似乎包含它以避免此警告,所以我会认真从 catch 块中删除 NullPointerException。这并不能帮助您避免警告。如果你想让我解释为什么它不好,你可以发表评论,我会的,否则就相信我的话,它对你没有帮助。

【讨论】:

  • 感谢您解释 NPE 是如何发生的。这让我对它有了更多的了解。但是我相信我初始化 fileFile 的方式使得它不可能变为空。我只想获取调用已编译 jarfile 的路径,并且通常永远不会是空值。
  • 从你所说的来看,你认为初始化是在上述代码的 try 块中完成的,这可能是也可能不是。声明将是这个File fileFile;,初始化是你第一次给它分配一个值(即使它是空的)。如果fileFile = ... 位于 try 块上方的任何位置,则它不会在那里被初始化。
  • 至于Main.class.getProtectionDomain().getCodeSource().getLocation().toURI() 永远不会为空,我不知道,我以前从未这样做过。
猜你喜欢
  • 2017-02-12
  • 2022-08-09
  • 2011-05-27
  • 1970-01-01
  • 1970-01-01
  • 2016-09-14
  • 1970-01-01
  • 2014-03-03
  • 1970-01-01
相关资源
最近更新 更多