=======================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值,从而存储两遍。)

String研究的更多相关文章

  1. Java复习3.变量.常量.String.

    Java 中的变量常量数据类型 20131004 前言: 还是国庆节,无聊的很,就没事复习点Java的知识,其实C/C++基本上是现在大型企业面试的语言,但是多学习点Java是没有坏处的,而且,将来工 ...

  2. std::string的find问题研究

    https://files-cdn.cnblogs.com/files/aquester/std之string的find问题研究.pdf 目录 目录 1 1. 前言 1 2. find字符串 1 3. ...

  3. Springboot 错误信息:Required String parameter 'loginname' is not present 引发的研究

    @PostMapping("/reg/change")public CommonSdo change( @RequestParam(value = "oldPasswor ...

  4. JavaScript String 对象实例深入研究

    本文主要介绍并分析JavaScript中String对象的具体用法,以及和String对象相关的方法,方便开发者在JavaScript开发中更好地处理字符串. 1. 介绍 String 对象,对字符串 ...

  5. C++标准库之string返回值研究

    先说结论(不一定适用所有环境): 1) GCC默认开启了返回值优化(RVO),除非编译时指定“-fno-elide-constructors”: 2) 现代C++编译器一般都支持返回值优化: 3) s ...

  6. std::string的拷贝赋值研究

    说明:以下涉及的std::string的源代码摘自4.8.2版本.结论:std::string的拷贝复制是基于引用计数的浅拷贝,因此它们指向相同的数据地址. // std::string类定义type ...

  7. java string字符拼接符"+"的研究

    程序: public class Test { public static void main(String args[]) { String s1 = "abc"; String ...

  8. String和StringBuffer的一点研究

    转载自:http://www.cnblogs.com/heshan664754022/archive/2013/03/15/2961463.html 首先请看下下面的这几个输出的结果,请仔细考虑,不要 ...

  9. 闲来无聊,研究一下Web服务器 的源程序

    web服务器是如何工作的 1989年的夏天,蒂姆.博纳斯-李开发了世界上第一个web服务器和web客户机.这个浏览器程序是一个简单的电话号码查询软件.最初的web服务器程序就是一个利用浏览器和web服 ...

随机推荐

  1. iOS开发-自动布局之autoresizingMask使用详解(Storyboard&Code)

    前言:现在已经不像以前那样只有一个尺寸,现在最少的IPHONE开发需要最少需要适配三个尺寸.因此以前我们可以使用硬坐标去设定各个控件的位置,但是现在的话已经不可以了,我们需要去做适配,也许你说可以使用 ...

  2. H5页面在IOS下不会自动播放音乐的坑

    document.addEventListener(‘DOMContentLoaded‘, function () { function audioAutoPlay() { var audio = d ...

  3. C# DateTime的11种构造函数

    别的也不多说没直接贴代码 using System; using System.Collections.Generic; using System.Globalization; using Syste ...

  4. PHP经常使用正則表達式汇总

    1.    平时做站点常常要用正則表達式,以下是一些解说和样例,仅供大家參考和改动使用:  2.    "^\d+$" //非负整数(正整数 + 0)  3.    "^ ...

  5. silverlight 对ChildWindow返回给父窗体值的理解(转载)

    这篇文章是我对ChildWindow的理解,举例说明: 有时候在项目中需要弹出子窗体进行一些操作,然后将操作的值返回到父窗体中. 下图是子窗体的界面(比较粗糙....) 下面贴出其代码: 子窗体前台代 ...

  6. 前端模块化和AMD、CMD规范

    前端模块化和AMD.CMD规范 先看下基础:https://github.com/seajs/seajs/issues/547

  7. NIO之Charset类字符编码对象

    Charset类字符编码对象 介绍 java中使用Charset来表示编码对象 This class defines methods for creating decoders and encoder ...

  8. C语言基础(18)-内存

    一.内存布局 1.1 代码区 代码区code,程序被操作系统加载到内存的时候,所有的可执行代码都加载到代码区,也叫代码段.代码区是可读不可写的. 代码区中的所有的内容在程序加载到内存的时候就确定了,运 ...

  9. docker的使用01

    使用Dockerfile构建镜像 vim dockerfile01 #注释信息 FROM ubuntu:latest //导入镜像 MAINTAINER leo "leo@leo.com&q ...

  10. iOS Socket/Tcp编程 GCDAsyncSocket的实战(带回调)

    很多同学一听到Socket TCP UDP 这几个字眼感觉特别害怕,很怕在工作当中使用,因为他们太底层了.下面我把我在工作中使用Socket类库GCDAsyncSocket进行一次实战 文章中只适用于 ...