JAVA中如何巧妙的避开空指针

  • Post author:
  • Post category:java



equals方法

Object类中的equals 方法在非空对象引用上实现相等关系,具有对称性a.equals(b) 和 b.equals(a) 结果是一样的,但当a == null时会抛出空指针异常

        import java.util.Objects;


        String a=null;
        String b="";
        System.out.println(a.equals(b));//异常

我们可以通过使用如下的方式来规避掉这个问题

        String a=null;
        String b="";
        System.out.println(b.equals(a));

但是,使用这种方式的前提是,我们非常的清楚的知道某一个参与比较的值,一定不为空,但是有时候,我们不确定参与比较的值是否为空,假如都为空的话,那么仍然可能会报空指针异常。

这个时候就需要使用Objects中的equals方法来比较

        String a = null;
        String b = null;
        System.out.println(Objects.equals(a, b));

使用这种方式,即使a或者b都是空的,仍然不会出现空指针,可以巧妙的避开空指针。

Objects中的equals方法,源代码如下:

    public static boolean equals(Object a, Object b) {
        return (a == b) || (a != null && a.equals(b));
    }

可以比较两个基本数据类型的数值是否相等,而equals方法依旧调用的是Object对象中的方法,比较俩个Object对象的地址值是否引用的同一块地址,如果不同则为false

而Objects还有一个名为deepEquals的方法,功能比较强大,不光能比较两个基本类型是否相等,还能够比较两个对象的内容是否相同,所以比较两个对象的内容是否相同的时候,我们应该使用deepEquals方法。

源代码如下:

    public static boolean deepEquals(Object a, Object b) {
        if (a == b)
            return true;
        else if (a == null || b == null)
            return false;
        else
            return Arrays.deepEquals0(a, b);
    }

    static boolean deepEquals0(Object e1, Object e2) {
        assert e1 != null;
        boolean eq;
        if (e1 instanceof Object[] && e2 instanceof Object[])
            eq = deepEquals ((Object[]) e1, (Object[]) e2);
        else if (e1 instanceof byte[] && e2 instanceof byte[])
            eq = equals((byte[]) e1, (byte[]) e2);
        else if (e1 instanceof short[] && e2 instanceof short[])
            eq = equals((short[]) e1, (short[]) e2);
        else if (e1 instanceof int[] && e2 instanceof int[])
            eq = equals((int[]) e1, (int[]) e2);
        else if (e1 instanceof long[] && e2 instanceof long[])
            eq = equals((long[]) e1, (long[]) e2);
        else if (e1 instanceof char[] && e2 instanceof char[])
            eq = equals((char[]) e1, (char[]) e2);
        else if (e1 instanceof float[] && e2 instanceof float[])
            eq = equals((float[]) e1, (float[]) e2);
        else if (e1 instanceof double[] && e2 instanceof double[])
            eq = equals((double[]) e1, (double[]) e2);
        else if (e1 instanceof boolean[] && e2 instanceof boolean[])
            eq = equals((boolean[]) e1, (boolean[]) e2);
        else
            eq = e1.equals(e2);
        return eq;
    }

toString()方法和valueOf()

很多时候为了图方便,需要将某个对象转换为String的时候都是直接调用对象的toString()方法,可是这样有个问题,当那个对象是null的时候,再调用toString()方法又会带来空指针问题,我们这个时候,就应该使用valueOf()来进行转换

        Double d = null;
        System.out.println(String.valueOf(d));
        System.out.println(d.toString());// 异常


Optional

因为有时候,我们可能会出现链式调用的情况,比如

school.getMajor("计算机").getTeacher().getName();

为了避免空指针,我们需要不断的if,如果调用的层次越多,那么if的嵌套就会越深,上面的那段代码就会变成如下这样

        if (school!=null) {
            Major major=school.getMajor("计算机");
            if (major!=null) {
                Teacher teacher=major.getTeacher();     
                if (teacher!=null) {
                    String name=teacher.getName();
                }
            }
        }

因为个人原因,我觉得这样非常的不美观,不和谐,为了避免空指针,没有办法。不过,现在有了新的方法来解决这个问题,上面的代码就可以改写成如下

String name=Optional.ofNullable(school)
                    .map(school -> school.getMajor("计算机"))
                    .map(Teacher::getName)
                    .orElse("Not Find");

这样,就可以保证在链式调用的时候,不会出现空指针,以为根据定义,Optional是一个可能存在也可能不存在的值,我们可以通过他的ifPresent方法去判断对象中是否存在值,通过orElseThrow方法,在没有值的时候直接甩出异常等等


就想到这么多,后续想到了再来补充



版权声明:本文为qq_28024699原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。