ThreadLocal拆装箱引起的空指针异常

ThreadLocal拆装箱引起的空指针异常

public class SpringbootApplication {

    /**
     * 登录方法
     *
     * @param userId
     */
    public void login(Integer userId) {
        UserInfoHolder.userInfoHolder.set(userId);
        System.out.println("用户登录了," + "保存用户id:" + userId);
        order();
    }

    /**
     * 下订单方法
     */
    public void order() {
        System.out.println("订单服务获取了用户id:" + UserInfoHolder.userInfoHolder.get() + ",下了订单");
        logistics();
    }

    /**
     * 物流方法
     */
    public void logistics() {
        UserInfoHolder.userInfoHolder.remove();
        System.out.println("物流服务获取了用户id:" + UserInfoHolder.get() + ",发出了物流");
    }

    /**
     * ThreadLocal
     */
    static class UserInfoHolder {
        private static ThreadLocal<Integer> userInfoHolder = new ThreadLocal<>();

        /**
         * 自定义了一个get方法,返回int类型
         *
         * @return
         */
        public static int get() {
            return userInfoHolder.get();
        }
    }


    public static void main(String[] args) throws Exception {
        new SpringbootApplication().login(666);
    }
}

运行结果:
ThreadLocal拆装箱引起的空指针异常_第1张图片

报了空指针异常

看下原因:

以下是userInfoHolder.get()的get方法的源码:

public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }
    
private T setInitialValue() {
        T value = initialValue();
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
        return value;
    }

 protected T initialValue() {
        return null;
    }

可以发现它返回的是一个泛型T,而这个T的类型是在ThreadLocal初始化就定义好的了,同时如果没有做任何初始化赋值,或者设值操作,默认就会返回null

以下ThreadLocal类的定义:

public class ThreadLocal<T> {
}

而上述测试代码中,初始化ThreadLocal时,定义的类型是Integer,所以get方法返回的也是Integer类型,由于调用了ThreadLocal的remove操作,所以默认会返回null,照理说返回null也没什么问题,关键就是方法里返回参数用的是int类型做接收,这样就会自动拆装箱,而由于值为null,自然就引起了空指针异常。返回值改为Integ返回er就ok了,运行结果就变成下面这样了:
在这里插入图片描述

总结

以上就是ThreadLocal拆装箱引起的空指针异常,了解一下就好。

你可能感兴趣的:(Java并发编程)