java.lang.nullpointerexception.
在本教程中,我们将看到最常用的Java异常:nullpointerexception。
它是运行时异常之一。
nullpointerexception的原因
由Java文档定义的nullpointerexception的原因。
- 调用NULL对象的实例方法。
- 访问或者修改NULL对象的字段。
- 占用空长度,就像它是一个数组一样。
- 访问或者修改空插槽,就像它是数组一样。
- 扔空虚,好像它是一个扔的价值。
- 当我们添加NULL到不允许诸如ConcurrentHashMap等空的集合
- 尝试使用null对象同步。
让我们详细了解这些中的每一个。
我正在创建一个我们将在我们的例子中使用的员工程序。
package org.igi.theitroad; public class Employee { String name; int age; public Employee() { } public Employee(String name, int age) { this.name=name; this.age=age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
1.调用NULL对象的实例方法
这是最明显的。
package org.igi.theitroad; public class InvokingMethodOnNullMain { public static void main(String[] args) { Employee e1=null; String name = e1.getName(); System.out.println("Employee Name: "+ name); } }
运行上面的程序时,我们将得到以下输出。
Exception in thread “main" java.lang.NullPointerException at org.igi.theitroad.comvokingMethodOnNullMain.main(InvokingMethodOnNullMain.java:7)
正如我们所见,E1在第7行是空,我们正在调用GetMethod,这就是为什么我们在这里获得NullPointerException。
2.访问或者修改NULL对象的字段。
与null上的调用实例方法非常相似。
package org.igi.theitroad; public class NullFieldExampleMain { public static void main(String[] args) { Employee e1=null; String name = e1.name; System.out.println("Employee Name: "+ name); } }
运行上面的程序时,我们将得到以下输出。
Exception in thread “main" java.lang.NullPointerException at org.igi.theitroad.NullFieldExampleMain.main(InvokingMethodOnNullMain.java:8)
如我们所见,E1在第8行为空,我们正在访问E1的名称字段,这就是我们在此处获得NullPointerException的原因。
3.占用空长度,就像它是一个数组一样。
当我们尝试获取空闲数组的长度时,我们将获得nullpointerexception。
package org.igi.theitroad; public class NullArrayLengthMain { public static void main(String[] args) { Employee[] arrEmp=null; int length = arrEmp.length; System.out.println("Length of array: "+length); } }
运行上面的程序时,我们将得到以下输出。
Exception in thread “main" java.lang.NullPointerException at org.igi.theitroad.NullArrayLengthMain.main(InvokingMethodOnNullMain.java:9)
4.访问或者修改空的插槽,就像它是数组一样。
当我们尝试访问或者修改Array.let的Helthem的Null Slot时。
package org.igi.theitroad; public class InvokingMethodOnNullMain { public static void main(String[] args) { Employee[] arrEmp=null; System.out.println(arrEmp[3]); } }
运行上面的程序时,我们将得到以下输出。
Exception in thread “main" java.lang.NullPointerException at org.igi.theitroad.comvokingMethodOnNullMain.main(InvokingMethodOnNullMain.java:8)
5.击中空值,好像它是一个可口值。
当你扔掉空调。
package org.igi.theitroad; public class InvokingMethodOnNullMain { public static void main(String[] args) { throw null; } }
运行上面的程序时,我们将得到以下输出。
Exception in thread “main" java.lang.NullPointerException at org.igi.theitroad.comvokingMethodOnNullMain.main(InvokingMethodOnNullMain.java:7)
6.当我们将null添加到不允许unulls等null(如concurrenthashmap)
package org.igi.theitroad; import java.util.concurrent.ConcurrentHashMap; public class InvokingMethodOnNullMain { public static void main(String[] args) { ConcurrentHashMap<String, String> map=new ConcurrentHashMap<>(); map.put(null, "Dummy"); } }
运行上面的程序时,我们将得到以下输出。
Exception in thread “main" java.lang.NullPointerException at java.base/java.util.concurrent.ConcurrentHashMap.putVal(ConcurrentHashMap.java:1022) at java.base/java.util.concurrent.ConcurrentHashMap.put(ConcurrentHashMap.java:1017) at org.igi.theitroad.comvokingMethodOnNullMain.main(InvokingMethodOnNullMain.java:10)
7.尝试使用NULL对象同步。
在NULL对象上同步时,我们将获得nullpointerexception
package org.igi.theitroad; import java.util.concurrent.ConcurrentHashMap; public class InvokingMethodOnNullMain { public static void main(String[] args) { Object obj=null; synchronized (obj) { ConcurrentHashMap<String, String> map=new ConcurrentHashMap<>(); map.put("Dummy", "value"); } } }
运行上面的程序时,我们将得到以下输出。
Exception in thread “main" java.lang.NullPointerException at org.igi.theitroad.comvokingMethodOnNullMain.main(InvokingMethodOnNullMain.java:10)
检测nullpointerexception.
更容易检测nullpointerexception。
检查异常跟踪,它会将类名称,方法名称和行Number.go告诉我们到该行号,检查nullpointerexception的原因。
修复nullpointerexception.
让我们带上方案并修复nullpointerexception。
1.零检查
在调用方法或者字段之前检查null。
package org.igi.theitroad; public class InvokingMethodOnNullMain { public static void main(String[] args) { Employee e1=null; if(e1!=null) { String name = e1.getName(); System.out.println("Employee Name: "+ name); } } }
当我们运行上面的程序时,我们将无法获取nullpointerexcpetion。
2.在收集不允许空的集合中键或者值之前,请在键入键或者值之前检查
避免nullpointerexception的最佳实践
1.字符串比较
这是nullpointerexcpetion最常见的原因,让我们在举例的帮助下了解。
package org.igi.theitroad; public class StringComparisonMain { public static void main(String[] args) { Employee e1=new Employee(); if(e1.getName().equalsIgnoreCase("John")) { System.out.println("Employee Name is John"); } } }
正如我们未设置员工E1的名称,我们将在此处获取NullPointerException。
运行上面的程序时,我们将得到以下输出。
Exception in thread “main" java.lang.NullPointerException at org.igi.theitroad.StringComparisonMain.main(StringComparisonMain.java:8)
我们可以更改如下逻辑。
package org.igi.theitroad; public class StringComparisonMain { public static void main(String[] args) { Employee e1=new Employee(); if("John".equalsIgnoreCase(e1.getName())) { System.out.println("Employee Name is John"); } } }
这将避免nullpointerexception。
请注意,由于空缺,它可能会导致意外行为。
如果名称不能为员工零空缺,那么不要使用上述方法,因为它将在这种情况下忽略null名称。
2.使用可选
Java 8推出了一个名为可选的新类。
一般来说,我们在方法中找不到任何值,我们从中返回null,调用者检查null是否会恢复疼痛,以便检查null。
例如:
public static Employee findEmployee(List<Employee employeeList,String name) { for(Employee e:employeeList) { if(e.getName().equalsIgnoreCase(name)) { return e; } } return null; }
正如我们所看到的,如果我们没有在雇员主义者中找到员工,我们将从FindeMployee方法返回NULL。
调用者将从FindeMployee方法获取员工对象,并且可以调用RetName()方法,该方法又可以升级NullPointerException.You可以使用可选避免此类情况。
package org.igi.theitroad; import java.util.ArrayList; import java.util.List; import java.util.Optional; public class JavaOptionalMain { public static void main(String[] args) { List<Employee> employeeList = createEmployeeList(); Optional<Employee> employeeOpt = findEmployee(employeeList,"John"); if(employeeOpt.isPresent()) { Employee employee = employeeOpt.get(); System.out.println("Employee name: "+employee.getName()); } else { System.out.println("There is no employee with name John"); } } public static Optional<Employee> findEmployee(List<Employee> employeeList,String name) { for(Employee e:employeeList) { if(e.getName().equalsIgnoreCase(name)) { return Optional.of(e); } } return Optional.empty(); } public static List<Employee> createEmployeeList() { List<Employee> employeeList=new ArrayList<>(); Employee e1=new Employee("Adam",23); Employee e2=new Employee("Dave",34); Employee e3=new Employee("Carl",45); Employee e4=new Employee("Mohan",29); Employee e5=new Employee("Paresh",30); employeeList.add(e1); employeeList.add(e2); employeeList.add(e3); employeeList.add(e4); employeeList.add(e5); return employeeList; } }
There is no employee with name John
它会指示调用者而不是返回值可以为null。
3.使用Ternary Indertor
我们可以使用三元操作来检查null。
package org.igi.theitroad; public class InvokingMethodOnNullMain { public static void main(String[] args) { Employee e1=null; String name = e1==null?e1.getName():""; System.out.println("Employee Name: "+ name); } }
正如我们所看到的,我们在此处不会得到nullpointerexception。
4. 始终检查方法的参数
package org.igi.theitroad; public class InvokingMethodOnNullMain { public static void main(String[] args) { String str=null; int len=getLength(str); System.out.println("Length of String:"+ len); } public static int getLength(String str) { if(str!=null) { return str.length(); } else { return 0; } } }
5.使用apache常用的stricutils
我们可以使用StrictUtils类来处理大量字符串NULL和空字符串检查。
有时,我们需要检查字符串是否为空或者空,则可以使用strictutils的isempty方法来照顾它。