我使用x!=null以避免NullPointerException。还有其他选择吗?

if (x != null) {
    // ...
}

当前回答

问这个问题表明你可能对错误处理策略感兴趣。如何以及在哪里处理错误是一个普遍存在的体系结构问题。有几种方法可以做到这一点。

我最喜欢的是:允许异常在“主循环”或其他具有适当职责的函数中波动-捕获它们。检查错误情况并适当处理它们可以被视为一项专门的责任。

当然,也要看看面向方面编程——它们有很好的方法将if(o==null)handleNull()插入到字节码中。

其他回答

public class Null {

public static void main(String[] args) {
    String str1 = null;
    String str2 = "";

    if(isNullOrEmpty(str1))
        System.out.println("First string is null or empty.");
    else
        System.out.println("First string is not null or empty.");

    if(isNullOrEmpty(str2))
        System.out.println("Second string is null or empty.");
    else
        System.out.println("Second string is not null or empty.");
}

public static boolean isNullOrEmpty(String str) {
    if(str != null && !str.isEmpty())
        return false;
    return true;
}
}

输出

str1 is null or empty.
str2 is null or empty.

在上面的程序中,我们有两个字符串str1和str2。str1包含空值,str2为空字符串。

我们还创建了一个函数isNullOrEmpty(),顾名思义,它检查字符串是空还是空。它使用!=进行空检查null和字符串的isEmpty()方法。

简单地说,如果字符串不是null并且isEmpty()返回false,那么它既不是null也不是空的。否则,就是这样。

但是,如果字符串只包含空白字符(空格),则上述程序不会返回空。从技术上讲,isEmpty()看到它包含空格并返回false。对于带空格的字符串,我们使用string方法trim()来删除所有前导和尾随空格字符。

通过遵循问题的大多数其他答案,您可以避免很多事情,以避免NullPointerException。我只想添加Java9中引入的其他一些方法,以优雅地处理这种情况,并展示一些旧的方法也可以使用,从而减少您的工作量。

公共静态布尔值isNull(对象obj)如果提供的引用为null,则返回true,否则返回错误。自Java 1.8以来公共静态布尔值nonNull(对象obj)如果提供的引用为非null,则返回true,否则返回错误。自Java 1.8以来公共静态<T>T requireOnNullElse​(T对象,T默认对象)如果第一个参数为非null,则返回第一个参数,否则返回非空的第二个参数。自Java 9以来公共静态<T>T requireOnNullElseGet​(T obj,供应商<?扩展T>供应商)如果第一个参数为非空,则返回第一个参数,否则返回supplier.get()的非空值。自Java 9以来公共静态<T>T requireOnNull​(T obj,供应商<字符串>消息供应商)检查指定的对象引用是否为空,否则将引发自定义的NullPointerException。自Java 1.8以来

有关上述功能的更多详细信息,请参阅此处。

Null不是“问题”。它是完整建模工具集的一个组成部分。软件旨在模拟世界的复杂性,零承担其负担。Null表示Java等中的“无数据”或“未知”。因此,为这些目的使用null是合适的。我不喜欢“空对象”模式;我想谁来守护监护人的问题。如果你问我女朋友的名字,我会告诉你我没有女朋友。在Java语言中,我将返回null。另一种方法是抛出有意义的异常,以指示一些无法(或不希望)立即解决的问题,并将其委派到堆栈中较高的位置,以重试或向用户报告数据访问错误。

对于“未知问题”,给出“未知答案”。(如果从业务角度来看,这是正确的,请确保null安全)在使用前检查方法内的null参数一次,可以避免多个调用方在调用前检查它们。公共照片getPhotoOfThePerson(个人){if(person==null)返回null;//占用一些资源或密集计算//无论如何使用person对象。}前一条导致了正常的逻辑流程,无法从我的照片库中获取不存在的女友的照片。获取人物照片(me.getGirlfriend())它与即将推出的新Java API相匹配(展望未来)getPhotoByName(me.getGirlfriend()?。getName())虽然找不到存储在数据库中的照片是相当“正常的业务流程”,但我过去在一些其他情况下会使用下面这样的配对公共静态MyEnum parseMyEnum(字符串值);//抛出IllegalArgumentException公共静态MyEnum parseMyEnumOrNull(字符串值);不要讨厌键入<alt>+<shift>+<j>(在Eclipse中生成javadoc)并为公共API编写三个额外的单词。除了那些不阅读文档的人,这对所有人来说都绰绰有余。/***@return photo或null*/或/***@return photo,从不为空*/这是一种理论上的情况,在大多数情况下,您应该更喜欢java空安全API(以防它在10年后发布),但NullPointerException是Exception的子类。因此,它是Throwable的一种形式,表示合理的应用程序可能想要捕获的条件(javadoc)!要使用异常的第一个最大优点,并将错误处理代码与“常规”代码分开(根据Java的创建者),对我来说,捕捉NullPointerException是合适的。公共照片getGirlfriendPhoto(){尝试{return appContext.getPhotoDataSource().getPhotoByName(me.getGirlfriend().get-Name());}catch(NullPointerException e){返回null;}}可能会出现以下问题:问:如果getPhotoDataSource()返回null怎么办?答:这取决于业务逻辑。如果我找不到相册,我就不给你看照片。如果appContext未初始化怎么办?该方法的业务逻辑可以满足这一点。如果相同的逻辑应该更严格,那么抛出异常是业务逻辑的一部分,应该使用显式检查null(情况3)。新的Java Null安全API在这里更适合于有选择地指定哪些内容意味着,哪些内容不意味着在发生程序员错误时被初始化为快速失败。Q.可以执行冗余代码,并且可以获取不必要的资源。答:如果getPhotoByName()尝试打开一个数据库连接,创建PreparedStatement,最后将人名用作SQL参数,则可能会发生这种情况。未知问题的方法给出了未知答案(案例1)。在获取资源之前,该方法应检查参数,并在需要时返回“未知”结果。问:由于尝试关闭,这种方法会导致性能损失。A.软件应易于理解和修改。只有在这之后,人们才能考虑性能,而且只有在需要的时候!以及需要的地方!(来源)和许多其他)。PS.这种方法将是合理的,因为单独的错误处理代码和“常规”代码原则在某些地方是合理的。考虑下一个示例:public SomeValue calculateSomeValueUsingSophisticatedLogic(谓词谓词){尝试{Result1 Result1=performSomeCalculation(谓词);Result2 Result2=performSomeOtherCalculation(result1.getSomeProperty());Result3 Result3=performThirdCalculation(result2.getSomeProperty());Result4 Result4=performLastCalculation(result3.getSomeProperty());return result4.getSomeProperty();}catch(NullPointerException e){返回null;}}public SomeValue calculateSomeValueUsingSophisticatedLogic(谓词谓词){SomeValue结果=空;if(谓词!=null){Result1 Result1=performSomeCalculation(谓词);如果(result1!=null&&result1.getSomeProperty()!=空){Result2 Result2=performSomeOtherCalculation(result1.getSomeProperty());如果(result2!=null&&result2.getSomeProperty()!=空){Result3 Result3=performThirdCalculation(result2.getSomeProperty());如果(result3!=null&&result3.getSomeProperty()!=空){Result4 Result4=performLastCalculation(result3.getSomeProperty());if(result4!=null){result=result4.getSomeProperty();}}}}}返回结果;}PPS。对于那些快速向下投票(而且阅读文档的速度不太快)的人,我想说,我一生中从未遇到过空指针异常(NPE)。但这种可能性是Java创建者故意设计的,因为NPE是Exception的子类。我们在Java历史上有过这样一个先例:ThreadDeath是一个错误,不是因为它实际上是一个应用程序错误,而是因为它不打算被捕获!NPE比ThreadDeath更适合作为错误!但事实并非如此。仅当业务逻辑暗示时,才检查“无数据”。public void updatePersonPhoneNumber(长personId,字符串phoneNumber){如果(personId==空)回来DataSource DataSource=appContext.getStuffDataSource();个人=dataSource.getPersonById(personId);if(person!=null){person.setPhoneNumber(电话号码);dataSource.updatePerson(人);}其他{人员=新人员(personId);person.setPhoneNumber(电话号码);dataSource.insertPerson(个人);}}和public void updatePersonPhoneNumber(长personId,字符串phoneNumber){如果(personId==空)回来DataSource DataSource=appContext.getStuffDataSource();个人=dataSource.g

如果您使用(或计划使用)JetBrains IntelliJ IDEA、Eclipse或Netbeans等Java IDE或findbugs等工具,那么您可以使用注释来解决这个问题。

基本上,你有@Nullable和@NotNull。

您可以在方法和参数中使用,如下所示:

@NotNull public static String helloWorld() {
    return "Hello World";
}

or

@Nullable public static String helloWorld() {
    return "Hello World";
}

第二个示例无法编译(在IntelliJ IDEA中)。

在另一段代码中使用第一个helloWorld()函数时:

public static void main(String[] args)
{
    String result = helloWorld();
    if(result != null) {
        System.out.println(result);
    }
}

现在IntelliJ IDEA编译器将告诉您,检查是无用的,因为helloWorld()函数永远不会返回null。

使用参数

void someMethod(@NotNull someParameter) { }

如果你写的东西像:

someMethod(null);

这无法编译。

最后一个使用@Nullable的示例

@Nullable iWantToDestroyEverything() { return null; }

这样做

iWantToDestroyEverything().something();

你可以肯定这不会发生。:)

这是一个很好的方法,可以让编译器检查比通常更多的东西,并强制执行您的契约以使其更强大。不幸的是,并非所有编译器都支持它。

在IntelliJ IDEA 10.5及更高版本中,他们添加了对任何其他@Nullable@NotNull实现的支持。

查看博客文章更灵活和可配置的@Nullable/@NotNull注释。

有时,您可以使用对其参数进行操作的方法来定义对称操作:

a.f(b); <-> b.f(a);

如果你知道b永远不可能为空,你可以交换它。它对equals最有用:而不是foo.equals(“bar”);最好使用“bar”。equals(foo);。