String研究

=======================String===================================

String里的==和equals
Java String “equals”就是比较字符串的内容,由于以上程序中的所有字符串内容都是“test”,所以用equals比较它们都会相等。但是你是否知道Java中基类Obejct的equals方法跟“==”方法其实是一致的呢?只不过是String类继承Object类后,重载了equal的方法,使得其成为了比较字符串中的内容。

很好的理解了equals之后,现在让我们来研究一下“==”方法的扑朔迷离。
“==”是Java中的运算符,它比较的内容是两个对象的指针,也就是实际对象的地址(程序员无法重载)。

http://www.jb51.net/article/37899.htm

String里的+
String hello = "hello"; 
String hel = "hel"; 
String lo = "lo"; 
System.out.println(hello == "hel" + "lo"); 
System.out.println(hello == "hel" + lo);

第一个加法连接时,+号两边都是常量字符串,java就会将两者拼起来后到String Pool里找与之相等(用equals)的字符串,若存在则将其地址返回;不存在则在String Pool里新建一个常量对象,其值等于拼接后的字符串,并将其地址返回。 
第二个加法连接时,+号两边有一个是变量,此时,java会在堆里新建一个对象,其值是两字符串拼接后的值,此时返回的地址是堆中新对象的地址。

http://unique5945.iteye.com/blog/177812

创建字符串的方式很多,归纳起来有三类:
其一,使用new关键字创建字符串,比如String s1 = new String("abc");
其二,直接指定。比如String s2 = "abc";
其三,使用串联生成新的字符串。比如String s3 = "ab" + "c";
Cliff:
其四,使用串联和变量生成新的字符串。比如String s1; String s3 = "ab" + s1;


String对象的创建

String对象的创建也很讲究,关键是要明白其原理。
原理1:当使用任何方式来创建一个字符串对象s时,Java运行时(运行中JVM)会拿着这个X在String池中找是否存在内容相同的字符串对象,如果不存在,则在池中创建一个字符串s,否则,不在池中添加。

原理2:Java中,只要使用new关键字来创建对象,则一定会(在堆区或栈区)创建一个新的对象。

原理3:使用直接指定或者使用纯字符串串联("+")来创建String对象,则仅仅会检查维护String池中的字符串,池中没有就在池中创建一个,有则罢了!但绝不会在堆栈区再去创建该String对象。Cliff:但是涉及到变量的时候,仍然会创建一个新的堆字符串。

原理4:使用包含变量的表达式或concat来创建String对象,则不仅会检查维护String池,而且还会在堆栈区创建一个String对象。


另外,String的intern()方法是一个本地方法,定义为public native String intern(); intern()方法的价值在于让开发者能将注意力集中到String池上。当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。

参考:
http://zy19880423.iteye.com/blog/434118

* Note that it is generally necessary to override the {@code hashCode} method whenever this method is overridden, so as to maintain the general contract for the {@code hashCode} method, which states that equal objects must have equal hash codes.

需要注意的是,一般来说,如果重写了equals方法,都必须要重写hashcode方法,来确保具有相同引用的对象,能够具有同样的hashcode值。
虽然这个不是强制性的,但是如果不能保证相同的引用对象,没有相同的hashcode,会对系统留下很大隐患。


String类的equals方法

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;
}

String 类的hashcode 方法

public int hashCode() {
    int h = hash;
    if (h == 0 && value.length > 0) {
        char val[] = value;

        for (int i = 0; i < value.length; i++) {
            h = 31 * h + val[i];
        }
        hash = h;
    }
return h;
}

可以看到hashcode的计算公式为: s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
因此,对于同一个String,得出的hashcode必然是一致的
另外,对于空的字符串,hashcode的值是0


小结
1.字符串比较时用的什么方法,内部实现如何?
使用equals方法,先比较引用是否相同,后比较内容是否一致.

2.hashcode的作用,以及重写equal方法,为什么要重写hashcode方法?
hashcode是系统用来快速检索对象而使用,
equals方法是用来判断引用的对象是否一致,
当引用对象一致时,必须要确保其hashcode也一致,因此需要重写hashcode方法来确保这个一致性
(Cliff:如果两个对象通过覆盖equals而相等,但不重写HashCode,那么会导致两个相同的数据有不同的HashCode值,从而存储两遍。)

原文地址:https://www.cnblogs.com/findumars/p/3249437.html