共同学习Java源码--常用数据类型--String(五)

来源:互联网 发布:mysql 配置用户名密码 编辑:程序博客网 时间:2024/05/21 17:11
    public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;

    }

equals方法非常重要,很多考菜鸟的面试题都会问==和equals什么区别,然后一些官方答案就是==判断的是引用,equals判断的是值,其实要是看了源代码,不会说出这么浅显的答案。String重写了Object的equals方法,String的equals方法首先判断是不是同一个对象,如果是就返回true。接下来判断参数是否是String类对象,不是的话就返回false,是的话先进行强转,然后获取String的char数组value的长度,如果两者的char数组value的长度不一样,也将返回false,然后用while循环判断两个char数组的每一个元素是否相等,如果不等就返回false。

    public boolean contentEquals(StringBuffer sb) {
        return contentEquals((CharSequence)sb);
    }


    private boolean nonSyncContentEquals(AbstractStringBuilder sb) {
        char v1[] = value;
        char v2[] = sb.getValue();
        int n = v1.length;
        if (n != sb.length()) {
            return false;
        }
        for (int i = 0; i < n; i++) {
            if (v1[i] != v2[i]) {
                return false;
            }
        }
        return true;
    }

   public boolean contentEquals(CharSequence cs) {
        // Argument is a StringBuffer, StringBuilder
        if (cs instanceof AbstractStringBuilder) {
            if (cs instanceof StringBuffer) {
                synchronized(cs) {
                   return nonSyncContentEquals((AbstractStringBuilder)cs);
                }
            } else {
                return nonSyncContentEquals((AbstractStringBuilder)cs);
            }
        }
        // Argument is a String
        if (cs instanceof String) {
            return equals(cs);
        }
        // Argument is a generic CharSequence
        char v1[] = value;
        int n = v1.length;
        if (n != cs.length()) {
            return false;
        }
        for (int i = 0; i < n; i++) {
            if (v1[i] != cs.charAt(i)) {
                return false;
            }
        }
        return true;
    }

这三个方法要一起看,第一个方法调用了第三个方法,第二个方法其实就是equals方法内部的实现,很奇怪干嘛单提出来,看来甲骨文也有不巧妙的地方,当然也许我水平低看不出人家的玄机。

第三个方法是判断内容相等与否。传入一个CharSequence对象cs,判断该对象是不是AbstractStringBuilder的子类,StringBuffer和StringBuilder都继承自AbstractStringBuilder类,然后AbstractStringBuilder类又实现了CharSequence接口。

如果确实是AbstractStringBuilder的子类,则判断是否为StringBuffer,如果是StringBuffer那么先给cs上锁,用上面的第二个方法进行判断,如果不属于StringBuffer,则直接用上面第二个方法判断。

为什么要给cs加锁呢?StringBuffer不是线程安全的么?没错,StringBuffer内部方法都是同步方法,但是如果cs作为一个参数传入的话尽管内部是同步的,也会在多线程环境下在方法内出现脏读等现象。因为我觉得StringBuffer个别方法比如insert方法就不是线程安全的。

如果判断cs为String,则直接调用equals方法进行判断。

如果cs为其他CharSequence的实现类,则还要按照equals方法那样进行判断value的每个元素都相等

0 0
原创粉丝点击