java.lang.nullpointerexception.

时间:2020-02-23 14:35:02  来源:igfitidea点击:

在本教程中,我们将看到最常用的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方法来照顾它。