<pre name="code" class="java"><pre name="code" class="html">英文原文地址:http://examples.javacodegeeks.com/java-basics/exceptions/java-lang-nullpointerexception-how-to-handle-null-pointer-exception/?utm_source=tuicool在Java语言在,null被分配给一个对象的引用以表示对象指向未知数据块。当应用程序使用或访问一个指向null的引用, NullPointerException 会被抛出。 下列情况会抛出NullPointerException 。
为什么我们需要null值?
如前所述,null是一个Java中的特殊值。null在编写一些设计模式时非常有用。例如Null对象模式[1] 与单例模式。Null对象模式提供一个对象作为缺少给定类型对象的代理。单例模式确保只有一个类的实例被创建,并且提供一个对象的全局访问点。
例如,至多创建类的一个实例的一种简单的方法是声明类的所有构造函数给私有类型,并创建一个公共方法,该方法返回这个类的唯一实例。
TestSingleton.java:
import java.util.UUID; class Singleton { private static Singleton single = null; private String ID = null; private Singleton() { /* Make it private, in order to prevent the creation of new instances of * the Singleton class. */ ID = UUID.randomUUID().toString(); // Create a random ID. } public static Singleton getInstance() { if (single == null) single = new Singleton(); return single; } public String getID() { return this.ID; } } public class TestSingleton { public static void main(String[] args) { Singleton s = Singleton.getInstance(); System.out.println(s.getID()); }在这个例子中,我们声明了一个Singletion类的静态实例。这个实例被在getInstance 方法中被初始化一次。注意,使用null值能使我们能够创建唯一的实例。
如何避免空NullPointerException
为了避免NullPointerException,确保所有对象在你使用之前被初始化。注意,当你声明一个变量的引用时,你正在创建一个指向一个对象的指针。在你使用该对象的方法或域之前,你必须检验指针不为null。
如果一个异常被抛出,使用在异常栈轨迹中驻留的信息。执行程序的栈轨迹由JVM提供,为了能够调试应用程序。定位产生异常的方法及异常被捕获所在的行,以找出在哪些行上,哪些引用为null。在本节剩余部分,我们将描述一些处理前文提到的异常所使用的技术。
1. 带有字面值的字符串比较
在应用程序代码中一种常见的情况是将字符串变量与字面值进行比较。字符串字面值可能是字符串或枚举元素。我们将通过使用字面值来调用方法,而不是通过使用null对象来调用方法。例如,观察下面的例子:
String str = null; if(str.equals("Test")) { /* The code here will not be reached, as an exception will be thrown. */ }
上面的代码片段会抛出NullPointerException。然后,如果通过字面值来调用方法,程序会正常执行。
String str = null; if("Test".equals(str)) { /* Correct use case. No exception will be thrown. */ }2.检查一个方法的参数
public static int getLength(String s) { if (s == null) throw new IllegalArgumentException("The argument cannot be null"); return s.length(); }
4. 使用三元运算符
三元运算符能帮助我们避免NullPointerException.运算符具有这样的形式:
boolean expression ? value1 : value2;
三元运算符能帮助我们避免NullPointerException.运算符具有这样的形式:首先,计算布尔表达式,如果表达式为true,value1被返回,否则value2被返回。我们能使用三元运算符来处理null指针,例如:
String message = (str == null) ? "" : str.substring(0, 10);
变量message将为空,如果str的引用为null,否则,如果str指向实际的数据,message将获取str的前10个字符。
5.创建返回空集合而不是null的方法
一种非常好的技术是创建一个返回空集合的方法,而不是返回null值。你的应用程序代码可以迭代空集合并使用它的方法和域,而不会抛出NullPointerException。例如:
public class Example { private static List<Integer> numbers = null; public static List<Integer> getList() { if (numbers == null) return Collections.emptyList(); else return numbers; } }6.利用Apache的 StringUtils类
7. 使用contains(), containsKey(), containsValue() 方法
如果你的程序使用了像Maps这样的集合,考虑使用contains(), containsKey(), containsValue()方法。例如,在验证某些键存在与Map中时,返回特定键的值。
Map<String, String> map = … … String key = … String value = map.get(key); System.out.println(value.toString()); // An exception will be thrown, if the value is null.在上面的片段中,我们不检查键是否存在与Map中,返回值可能为null.最安全的方式是:
Map<String, String> map = … … String key = … if(map.containsKey(key)) { String value = map.get(key); System.out.println(value.toString()); // No exception will be thrown. }8.检查外部方法的返回值
public static int getLength(String s) { /* Ensure that the String is not null. */ assert (s != null); return s.length(); }
最后,你可以使用由Junit测试框架提供的Assert类。
存在NullPointerException的安全方法
1.访问静态成员或类方法
当你的代码试图访问静态变量或一个类的方法,即使对象的引用等于null,JVM也不会抛出NullPointerException.这是因为,在编过程中,Java编译器存储静态方法和域在特殊的位置。静态方法和域不与对象关联,而是与类名关联。
例如下面的代码不会抛出NullPointerException.
class SampleClass { public static void printMessage() { System.out.println("Hello from Java Code Geeks!"); } } public class TestStatic { public static void main(String[] args) { SampleClass sc = null; sc.printMessage(); } }注意,尽管SampleClass的实例为null,方法还是会被执行。当方法或域为静态时,应该以“静态”的方式来访问,即通过类名来访问。例如:SampleClass.printMessage()
2. instanceof 操作符
即使对象的引用为null,instanceof操作符可使用。当引用为null时,instanceof 操作符返回false,而且不会抛出NullPointerException.例如,下面的代码:
String str = null; if(str instanceof String) System.out.println("It's an instance of the String class!"); else System.out.println("Not an instance of the String class!");
Not an instance of the String class!
[1] Null Object pattern, https://en.wikipedia.org/wiki/Null_Object_pattern.