我有一个朋友,写代码的时候常常遭到NPE背刺,痛定思痛,总结了NPE出没的17个场景,哪一个你还没有遇到过?
虽然无法统计出Java程序员写的最多的异常是哪一个,NullPointerException(NPE)它一定会榜上有名。无论是初次涉足编程世界的新手,还是在代码海洋中久经风浪的老鸟,几乎都写过NPE异常。要防范它,不在高超的编码技巧,在细。
我有一个朋友,写代码的时候常常遭到NPE背刺,痛定思痛,总结了NPE出没的17个场景,哪一个你还没有遇到过?
从其它方法(如远程hsf方法或者从DB)返回的结果,不做控制判断,直接访问变量或者方法,可能会NPE。
public class Test {
public String a;
public String getA() {
return a;
}
public static void main(String[] args) {
Test test = getFromSomeMethod();
System.out.println(test.a);
System.out.println(test.getA());
}
private static Test getFromSomeMethod() {
return null;
}
}
public class Test {
public static void main(String[] args) {
int[] numbers = getFromSomeMethod();
int number = numbers[0];
numbers[0] =1;
}
private static int[] getFromSomeMethod() {
return null;
}
}
public class Test {
private String a;
public String getA() {
return a;
}
public static void main(String[] args) {
Test[] testArr = new Test[2];
testArr[0].getA();
}
}
在Java中,通常不会故意使用
throw null
这种表达,因为它实际上没有任何有用的用途。根据Java语言规范,
throw
关键字后面应该跟随一个可抛出的对象(Throwable 类或其子类的实例),而
null
并不是一个可抛出的对象。如果你执行
throw null
,将会得到一个
NPE
。
-
代码错误:
throw null
可能是代码编写错误或者不完整的异常处理。例如,可能打算抛出一个实际的异常对象,但误写成了
null
。
-
测试代码:在单元测试中,有时可能会故意使用
throw null
, 来确保他们的异常处理代码能够妥善处理意外情况。(不推荐)
public class Test {
public static void main(String[] args) {
getFromSomeMethod();
}
private static int getFromSomeMethod() {
try {
int a = 1/0;
}catch (Exception e){
throw null;
}
return 0;
}
}
5.在null 引用上进行synchronized同步
public class Test {
public static void main(String[] args) {
Test test = getFromSomeMethod();
synchronized (test){
}
}
private static Test getFromSomeMethod() {
return null;
}
}
自动装箱不会遇到
Null
的问题,因为这个过程是把基本类型的值转换成包装类对象,基本类型的值是没有
Null
的。
public class Test {
public static void main(String[] args) {
Integer integer = getFromSomeMethod();
if (integer > 1) {
}
}
private static Integer getFromSomeMethod() {
return null;
}
}
定义方法返回一个int 作为出参,但实际return 一个null,也会NPE。
public static void main(String[] args) {
getFromSomeMethod();
}
private static int getFromSomeMethod() {
Integer a = null;
return a;
}
从集合/map中获取元素并使用时,建议对
Null
进行检查,以避免潜在的NPE,特别是在那些隐式触发自动拆箱的场景中。
Map<String, String> map = new HashMap<>();
String value = map.get("key");
int length = value.length();
Test test = new Test().getA().getB().getC();
Enum enum = Enum.valueOf(null);
HashSet 、LinkedHashSet 都只允许添加一个null。后续无论添加多少null元素,都会被忽视。
TreeSet 不允许添加null值,排序集合依赖元素直接的比较操作,而null元素不能与其它对象进行比较,会抛出
NPE
;
Set<String> set = new TreeSet<>();
set.add(null);
public class Test implements Runnable {
private static String sharedResource;
public void run() {
sharedResource = "sharedResource";
}
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new Test());
thread.start();
System.out.println(sharedResource.length());
}
}
required属性为false,启动过程中如果没有找到合适的bean,service 会被设置为null。在调用service的任何方法之前
都需要判断
service是否为null。