zoukankan      html  css  js  c++  java
  • 阿里巴巴Java开发手册要点笔记 (一)

    1:【强制】Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。

    正例:"test".equals(object);

    反例:object.equals("test");

    说明:推荐使用 java.util.Objects#equals(JDK7 引入的工具类)。其就是实例对象equals的一个健壮版本

    实现:

        /**
         * Returns {@code true} if the arguments are equal to each other
         * and {@code false} otherwise.
         * Consequently, if both arguments are {@code null}, {@code true}
         * is returned and if exactly one argument is {@code null}, {@code
         * false} is returned.  Otherwise, equality is determined by using
         * the {@link Object#equals equals} method of the first
         * argument.
         *
         * @param a an object
         * @param b an object to be compared with {@code a} for equality
         * @return {@code true} if the arguments are equal to each other
         * and {@code false} otherwise
         * @see Object#equals(Object)
         */
        public static boolean equals(Object a, Object b) {
            // 可以巧妙避开空指针异常。首先判断a==b,在判断a!=null,如果a==null的话此时a.equals(b)短路
            return (a == b) || (a != null && a.equals(b));
        }

    2:java.util.Objects.deepEquals(Object, Object)方法讲解分析,源码如下:

       /**
        * Returns {@code true} if the arguments are deeply equal to each other
        * and {@code false} otherwise.
        *
        * Two {@code null} values are deeply equal.  If both arguments are
        * arrays, the algorithm in {@link Arrays#deepEquals(Object[],
        * Object[]) Arrays.deepEquals} is used to determine equality.
        * Otherwise, equality is determined by using the {@link
        * Object#equals equals} method of the first argument.
        *
        * @param a an object
        * @param b an object to be compared with {@code a} for deep equality
        * @return {@code true} if the arguments are deeply equal to each other
        * and {@code false} otherwise
        * @see Arrays#deepEquals(Object[], Object[])
        * @see Objects#equals(Object, Object)
        */
        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);
        }

    java.util.Arrays.deepEquals0(Object, Object)源码如下:

       static boolean deepEquals0(Object e1, Object e2) {
            assert e1 != null;
            boolean eq;
         // 如下的equals是Arrays中的equals方法,是对每一个元素进行比较
    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; }

    java.util.Arrays.equals(char[], char[])源码如下:

    /**
         * Returns <tt>true</tt> if the two specified arrays of chars are
         * <i>equal</i> to one another.  Two arrays are considered equal if both
         * arrays contain the same number of elements, and all corresponding pairs
         * of elements in the two arrays are equal.  In other words, two arrays
         * are equal if they contain the same elements in the same order.  Also,
         * two array references are considered equal if both are <tt>null</tt>.<p>
         *
         * @param a one array to be tested for equality
         * @param a2 the other array to be tested for equality
         * @return <tt>true</tt> if the two arrays are equal
         */
        public static boolean equals(char[] a, char[] a2) {
            if (a==a2)
                return true;
            if (a==null || a2==null)
                return false;
    
            int length = a.length;
            if (a2.length != length)
                return false;
    
            for (int i=0; i<length; i++)
                if (a[i] != a2[i])
                    return false;
    
            return true;
        }

    示例1:对于基本类型的数组,元素相同,使用Objects的equals方法判定是false,但是对于deepEquals方法是对底层每一个元素调用其equals判断是否相等。

            int[] a = { 1, 2, 3, 4, 5 };
            int[] b = { 1, 2, 3, 4, 5 };
            // 数组的equals方法其实就是直接判断引用是否相等,不会具体判断每一个元素
            System.out.println(Objects.equals(a, b)); // false
            System.out.println(Objects.deepEquals(a, b)); // true

    示例2:

    实体类User,此版本实现了HashCode和equals方法

    class User {
        public String userName;
    
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((userName == null) ? 0 : userName.hashCode());
            return result;
        }
    
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            User other = (User) obj;
            if (userName == null) {
                if (other.userName != null)
                    return false;
            } else if (!userName.equals(other.userName))
                return false;
            return true;
        }
    
        public User(String userName) {
            super();
            this.userName = userName;
        }
    
        public User() {
            super();
            // TODO Auto-generated constructor stub
        }
    
        public String getUserName() {
            return userName;
        }
    
        public void setUserName(String userName) {
            this.userName = userName;
        }
    
    }

    此时:

            User[] u1 = { new User("daxin"), new User("mali") };
            User[] u2 = { new User("daxin"), new User("mali") };
            System.out.println(Objects.equals(u1, u2)); //false
            System.out.println(Objects.deepEquals(u1, u2)); //true,调用的User自己实现的equals方法

    示例3:没有实现hashcode和equals方法的User:

    class User {
        public String userName;
    
        public User(String userName) {
            super();
            this.userName = userName;
        }
    
        public User() {
            super();
            // TODO Auto-generated constructor stub
        }
    
        public String getUserName() {
            return userName;
        }
    
        public void setUserName(String userName) {
            this.userName = userName;
        }
    
    }

    此时:

            User[] u1 = { new User("daxin"), new User("mali") };
            User[] u2 = { new User("daxin"), new User("mali") };
            System.out.println(Objects.equals(u1, u2)); //false
            System.out.println(Objects.deepEquals(u1, u2)); //false,对底层每一个元素调用默认的equals方法(此时equals方法判定的是引用)

    3:【强制】所有的相同类型的包装类对象之间值的比较,全部使用 equals 方法比较。 说明:对于 Integer var = ? 在-128 至 127 范围内的赋值,Integer 对象是在IntegerCache.cache 产生,会复用已有对象,这个区间内的 Integer 值可以直接使用==进行 判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑, 推荐使用 equals 方法进行判断。

    示例:

           Integer a=12;
            Integer b=12;
            System.out.println(a==b);//true
            Integer c=1550;
            Integer d=1550;
            System.out.println(c==d);//false
            System.out.println(c.intValue()==d);//对c进行拆箱,所以导致d也拆箱。所以true
            System.out.println(c==d.intValue());//对d进行拆箱,所以导致c也拆箱。所以true
            System.out.println(c.intValue()==d.intValue());//都拆箱
            System.out.println(Objects.equals(c, d));//使用Objects的equals方法比较

    4:【推荐】使用索引访问用 String 的 split 方法得到的数组时,需做最后一个分隔符后有无 内容的检查,否则会有抛 IndexOutOfBoundsException 的风险。

    说明:

    String str = "a,b,c,,";
    String[] ary = str.split(",");
    // 预期大于 3,结果是 3
    System.out.println(ary.length);

    又如:

    System.out.println(",,,,".split(",").length); //0

    5:【强制】ArrayList的subList结果不可强转成ArrayList,否则会抛出ClassCastException 异常,即 java.util.RandomAccessSubList cannot be cast to java.util.ArrayList. 说明:subList 返回的是 ArrayList 的内部类 SubList,并不是 ArrayList ,而是 ArrayList 的一个视图,对于 SubList 子列表的所有操作最终会反映到原列表上。

            List<Integer> list =new ArrayList<>();
            list.add(1);
            list.add(2);
            List<Integer> subList = list.subList(0, list.size());
            System.out.println(subList);//[1, 2]
            subList.add(3); //对subList操作反映在list上
            System.out.println(list);//[1, 2, 3]
  • 相关阅读:
    Mysql分布式事务
    Mysql锁
    Mysql事务隔离级别
    java 资源监控
    Mysql子查询
    javaWeb四大域对象
    KVM 迁移
    KVM 虚拟化
    网络基础
    系统简单启动过程
  • 原文地址:https://www.cnblogs.com/leodaxin/p/7651154.html
Copyright © 2011-2022 走看看