今天修改辞职同事遗留的代码才发现这个问题,不能用 isEmpty 来判断一个对象是否为 null ,之前没在意这个问题,在报了空指针之后才发现这个问题。

查了一下关于判断为空的几个方法的区别,这里做一个简单的总结:

一个对象如果有可能是 null 的话,首先要做的就是判断是否为null: object == null ,否则就有可能会出现空指针异常,这个通常是我们在进行数据库的查询操作时,查询结果首先用 object != null ,进行非空判断,然后再进行其他的业务逻辑,这样可以避免出现空指针异常。

  1. isEmpty() 此方法可以使用于字符串,数组,集合都可以用。

首先看一下源码:

    public boolean isEmpty() {
        return value.length == 0;

这里是一个对象的长度,使用这个方法,首先要排除对象不为null,否则当对象为null时,调用isEmpty方法就会报空指针了。

要想返回true,也就是一个对象的长度为0,也就是说首先这个对象肯定不为null了,内容为空时,才能返回true。

这里我想到了之前看过视频里面说到的栈和堆的问题,当创建一个新的对象时,栈里面有一个对象,堆里面有一个对象,栈里的对象指向堆里面的对象。对象包含引用对象和实际对象,也就是栈和值的关系,比如String a = new String();,这句代码就在堆内存中产生了一个String对象"",和栈内存中一个引用对象a,也就是a指向了一个为空的字符串。当没有再次给引用对象a进行赋值时,操作a也即是操作这个空字符串。

栈内存:栈内存首先是一片内存区域,存储的都是局部变量,凡是定义在方法中的都是局部变量(方法外的是全局变量),for循环内部定义的也是局部变量,是先加载函数才能进行局部变量的定义,所以方法先进栈,然后再定义变量,变量有自己的作用域,一旦离开作用域,变量就会被释放。栈内存的更新速度很快,因为局部变量的生命周期都很短。

堆内存:存储的是数组和对象(其实数组就是对象),凡是new建立的都是在堆中,堆中存放的都是实体(对象),实体用于封装数据,而且是封装多个(实体的多个属性),如果一个数据消失,这个实体也没有消失,还可以用,所以堆是不会随时释放的,但是栈不一样,栈里存放的都是单个变量,变量被释放了,那就没有了。堆里的实体虽然不会被释放,但是会被当成垃圾,Java有垃圾回收机制不定时的收取。

下面我们通过一个图例详细讲一下堆和栈:

比如主函数里的语句 int [] arr=new int [3];在内存中是怎么被定义的:

主函数先进栈,在栈中定义一个变量arr,接下来为arr赋值,但是右边不是一个具体值,是一个实体。实体创建在堆里,在堆里首先通过new关键字开辟一个空间,内存在存储数据的时候都是通过地址来体现的,地址是一块连续的二进制,然后给这个实体分配一个内存地址。数组都是有一个索引,数组这个实体在堆内存中产生之后每一个空间都会进行默认的初始化(这是堆内存的特点,未初始化的数据是不能用的,但在堆里是可以用的,因为初始化过了,但是在栈里没有),不同的类型初始化的值不一样。所以堆和栈里就创建了变量和实体:
在这里插入图片描述

下面看一个demo:

	public static void main(String[] args) {
		String a = new String();
		String b = "";
		String c = null;
		if (a.isEmpty()) {
			System.out.println("String a is empty");
		if (b.isEmpty()) {
			System.out.println("String b is empty");
		if (c == null) {
			System.out.println("String c = null");
		if (null == a) {
			// 编译器直接就提示了Dead code,a指向了一个新对象,肯定不是null了
			System.out.println("String a =null");
		if (a == "") {
			System.out.println("a = ''");
		if (a.equals("")) {
			//由于a是字符串,字符串的比较需要用equals,不能直接用 ==
			System.out.println("a = ''");
		/*if (c.isEmpty()) {
			// 这里会报空指针,即null不能使用此方法
			System.out.println("c == null   and   c.isEmpty");
		List<String> list = new ArrayList<>();
		//list.add("");
		if (list.isEmpty()) {
			System.out.println("list is empty");
		System.out.println(list.size());
/*Output:
String a is empty
String b is empty
String c = null
equals:a = ''
list is empty

参考文章:
堆和栈的概念和区别 : https://blog.csdn.net/pt666/article/details/70876410/
JAVA中isEmpty和null以及""的区别 : https://blog.csdn.net/lhflower123/article/details/8223607

最近项目中遇到一个问题,在用户没填数据的时候,我们需要接收从前端传过来的对象null,但是前端说他们一个一个判断特别麻烦,只能传个空对象过来,我第一个想法就是可以通过反射来判断对象是否为空。 User.java public class User { private String username; private Boolean active; priva...... 一种是org.apache.commons.lang3包下的;另一种是org.springframework.util包下的。基本上判断对象是否为空,StringUtils.isEmpty(Object str)这个方法都能搞定。从上面的例子可以看出第二种的StringUtils类更实用。 String a = ""; a 就可以称为是一个空字符串。由于 String 在 Java 中底层是通过 char 数组去存储字符串的,所以空字符串对应的 char 数组表现形式为 private final char value[] = new char[0]; 但实际工作中,我们需要对字符串进行一些校验,比如:是否为 null是否为空,是否去掉空格、换行符、制表符等也不为空。比较简单的就 if(值!=null&&!值.equals("")){} 判断对象不是空 if (orderProds!=null && orderProds.isEmpty()!=true){} 带返回值判断,list如果是空赋值0,相反赋值list保存对象个数 return list == null ? 0 : list.size() nullisEmpty()都是用来判断是否为空;那为什么有的时候会做双重判断,比如要判断一个值为null并且isEmpty()呢? 首先,要看二者判断的区别: null→是判断是否分配内存空间; isEmpty()→是分配了内存空间,判断里边的值是否为空值,返回的结果为TRUE或FALSE; 所以,在实际应用场景中,应用最多的是同时判断两个条件,1判断是否分配内存并且2判断是否为空,示例代码如下: if (null != files && !files.isEmpty() 小伙伴们大家好,最近一段时间家里有点事,没空写博客,现在事忙完啦。今天趁周末写一篇文章,希望对大家有所帮助。java编写接口时总是会遇到传多个参数的情况,此时我们一般会习惯用对象封装。那么前端就需要给我们传递一个对象,而对象传过来后我们的必要操作就是首先判空,避免后续操作产生空指针或者其他错误。 一、object==null判断对象为空 这里我也是写了一个测试接口,首先使用object== 那么 str == null 和 str.isEmpty() 有什么实质上的区别: 划重点:String 类 是引用类(reference type),有别于java 8个primitive type( int, long, etc) null: 该对象是否存在 isEmpty(): 该对象存在,值是否为空 isEmptynull的区别: 1.isEmpty对象是否为空(IsNull),null是值为空IsEmpty) 2.isEmpty() 用于判断List内容是否为空,必须在 list 本身不是空的引用的情况下才行; null 用于判断有没有这个集合对象; 是否为空 IsNull函数: 功能:返回Boolean的值,指明表达是否不包含任何有效数据。NULL表示的是数据值未知或不可用,它不表示...