java应用避免NullPointerException的最佳方法@NotNull的使用

标签:

java应用避免NullPointerException的最佳方法

在java应用程序中,一个NullPointerException(空指针异常)是最好解决(问题)的方法。同时,空指针也是写健壮的顺畅运行的代码的关键。“预防好过治疗”这句话也同样适用于令人不爽的NullPointerException。通过应用防御性的编码技术和在遵守多个部分之间的约定,你可以再很大程度上避免NullPointerException。下面的这些java小技巧可以最小化像!=null这种检查的代码。作为经验丰富的java程序猿,你可能意识到这些技术的某部分项目当中使用它。但是对于大学一年级学生和中级开发者,这是一个很好的学习机会。

 

这是一些很容易学会的简单技术,但是对于代码质量和健壮性来说确实很重要。以我的经验,仅是第一个小技巧就已经对改进代码质量具有很大的作用了。

 

1)在已经的String(字符串)调用 equal()和 equalsingnoreCase()而不是未知的对象

通常在已经的非空字符串在调用equals()。因为equal()方法是对称的,调用a.equal()是同等于调用b.equal(),和这就是为什么很多部注意对象a和b,如果空的一边被调用会到导致空指针。

 

Object unknownObject = null;

//wrong way - may cause NullPointerException
if(unknownObject.equals("knownObject")){
   System.err.println("This may result in NullPointerException if unknownObject is null");
}

//right way - avoid NullPointerException even if unknownObject is null
if("knownObject".equals(unknownObject)){
    System.err.println("better coding avoided NullPointerException");
}

 

 

这是最重要的避免NullPointerException的java技巧,但是结果会是极大的改进,因为equal()是一个很普遍的方法。

 

 

2)在两者返回相同结果的时候偏向使用valueOf()而非toString()

因为空对象调用toString()时会抛出NullPointerException。如果我们可以通过调用value()得到相同的值的话,就应该使用valueOf()。这样会传递会一个空值。特别是在像Integer,Float,Double或者BigDecimla之类的包装类的情况下。

 

BigDecimal bd = getPrice();
System.out.println(String.valueOf(bd)); //doesn’t throw NPE
System.out.println(bd.toString()); //throws "Exception in thread "main" java.lang.NullPointerException"

 

 


如果你不确定你所使用的对象是否是空的时候,请使用这个JAVA技巧

 

3)使用空安全方法(null safe method)或者类库

现在有很多已经为你做了null检查的开源组件出现。其中一个最为普遍的就是Apache的StringUtils。你可以使用StringUtils.isBlank(),isNumberic(),isWhiteSpace()和其他工具一些不用担心NullPointerException方法。

 

System.out.println(StringUtils.isEmpty(null));
System.out.println(StringUtils.isBlank(null));
System.out.println(StringUtils.isNumeric(null));
System.out.println(StringUtils.isAllUpperCase(null));

Output:
true
true
false
false

 

但在作出任何结论之前,不要忘记阅读关于Null安全方法和类的文档。这是另一个java最佳操练,这不会要求你付出非常多的努力,但会让你获得很大的进步。

 

4)避免用返回空的collection或者空的array来代替从方法中返回Null

这个java技巧也是在Joshua Bloch的《Effective Java》所提及的。这本书也是一个提高JAVA编码能力的一个来源。通过返回一个空的collection或者一个空的array可以确定像size(),length()这种基础的调用不会抛出NullPointerException。Collection类能够提供方便的空的List,Set和Map,(这些)有Collections.EMPTY_LIST, Collections.EMPTY_SET和 Collections.EMPTY_MAP这些能够被使用的(静态变量)。

代码如下;

  public List getOrders(Customer customer){  

   List result = Collections.EMPTY_LIST;  

return result;  

}  

 

 

 

类似地你可以使用Collections.EMPTY_LIST, Collections.EMPTY_SET和 Collections.EMPTY_MAP来代替返回Null。

 

5)使用@NotNull和@Nullable注释

当写你可以定义关于约定可空性(Nullability),要通过使用像@NotNull和@Nullable类似的注释提示这个方法是否为空安全(null safe)。现代的编译器,IDE和其他工具可以读出这个注释来帮你做一个空检查或者告诉你是否需要空检查。IntelliJIDE和findbugs 已经支持这种注释。这些注释也是JSR 305(译者注:可以理解为java的标准)的一部分。通过看到@NotNull和@Nullable,程序猿可以自己决定是否去进行空检查。顺便说下,对于JAVA程序猿来说,这是新的最好的实践,尽管需要一点时间去适应。

 

7)遵循约定和定义合理的默认值

在java领域,一个最佳的避免空指针的方法之一就是和定下约定和遵守约定。大部分的NullPointerException发生原因就是使用了一个不完整的信息或者并没有被提供所有的依赖信息来创建对象。如果你不允许创建不完整的对象和否定任何这种要求,你可以预防很多一段时间之后发生的NullPointerException。如果对象被允许创建,那么你应该设定合理的默认值。例如,一个Employee(雇员)对象不可以在没有Id和Name属性的情况下被创建,但可以有一个可供选择的pghone number(电话号码)。如果Employee没有phone number,那么就用返回一个0来代替返回一个空值。但是这种处理必须非常小心地处理对空值的检查而不是检查非法输入。同样要注意,定义可以使空值的或者不可以空值的时候,提醒调用者作出被告知的决定。失败之后的选择或者接受空值也是一个你需要重视的重要设计。

 

8)如果你使用数据库去存储你的域对象(demain object),例如:Customer、Orders等等,那么你应该定义一些在数据库对空值的约束。因为数据库可以要求获得从多个来源来的数据,在数据库中拥有对空值的检查将会确保数据的完整性。在数据库中保留对空值约束的约束也是会让你减少在JAVA中减少空检查的代码。当从数据库中取出一个对象是,你可以确保那些属性可以是空而那些属性不可以使空,这将会让那些空检查的代码最小化。

 

9)使用空对象模式

这是另外一个在JAVA里面避免NullPointerException的方法。如果一个方法返回一个对象,哪个调用者要遍历这个对象,哪个调用者就要使用一些类似Collection.iterator()的方法去返回iterator。如果调用者没有任何的上述的这些方法,那么有可能返回的是空对象而不是空(null)。空对象是一个特别的对象,它在不同的上下文中有不同的含义。像这些返回Contrainter或者Conllection类型的方法的情况中,里面为空的对象(Empty object)应该被使用而不是返回空。

由@NotNull 注解引出的关于Java空指针的控制(转)

标签:

Java 编程中,`@NotNull`是一个用于标记字段、方法参数或其他对象不允许为 `null` 的注解。这个注解通常出现在依赖于非 `null` 对象的方法上,可以减少程序运行时可能出现的空指针异常 (`NullPointerException`)。 ### 使用 `@NotNull` 在引入 `@NotNull` 注解之前,你需要先在项目中引入相应的注解库。例如,在 Spring Boot 中,你可以通过添加对应的 Maven 或 Gradle 插件来支持这个注解。下面是在 Maven 项目的 `pom.xml` 文件中添加必要的依赖: ```xml <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> </dependencies> ``` 一旦导入了依赖,你就可以开始使用 `@NotNull` 注解了。这通常应用于以下几个场景: #### 示例一:数据验证 在创建一个需要验证输入值是否为空的对象时: ```java public class User { private String name; // 使用 @NotNull 注解来避免 null 参数传递给构造函数 public User(@NotNull String name) { this.name = name; } // 其他 getter 和 setter... } ``` 当你尝试实例化 `User` 类并且传入 `null` 作为参数时,IDE 或编译器会提示错误,因为 `name` 字段被标记为不可为 `null`。 #### 示例二:方法参数验证 在一个方法接收参数并期望该参数不是 `null` 的情况下: ```java import javax.validation.constraints.NotNull; public class UserService { public void processUser(@NotNull User user) { if (user == null) { throw new IllegalArgumentException("User cannot be null"); } // 处理用户... } } ``` 在这种情况下,如果 `processUser` 方法接收到 `null` 用户对象,那么 IDE 或者编译器将会警告,并且运行时也可能抛出异常。 ### 避免指针异常的好处 使用 `@NotNull` 可以带来几个显著的好处: 1. **提高代码质量和安全性**:强制开发者明确处理 `null` 情况,减少了潜在的运行时错误。 2. **增强可维护性**:通过消除或减少空指针异常,使得代码更容易理解和维护。 3. **团队协作**:当所有成员都采用相同的编码规范时,如使用 `@NotNull` 来管理 `null` 安全性,可以提高团队内部的代码一致性和易理解性。 ### 相关问题: 1. `@NotNull` 是否适用于所有类型的对象? 2. 如何自定义 `@NotNull` 校验消息? 3. 使用 `@NotNull` 后还需要其他校验措施吗?
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值