java基础之String初解

String是我们在java中经常使用到的一个引用数据类型,下面我们就来仔细了解下它的底层原理。

首先我们来看看String的源码

String存储的值被final修饰

/** The value is used for character storage. */

private final char value[];

这里我们可以看到,String内部是通过一个final所修饰的字符数组来存储字符串,既然被final所修饰,那么它的值只能被初始化而不能被修改,所以String的值在建立对象的时候就被固定了。

字符串拼接需要注意的地方

String a1 = "a";

a1 = a1 + "b";

如上图所示,既然a1所指向对象的值已在初始化的时候被固定为“a”,那么当执行完 a1 = a1 + “b”,为何 a1所指向的对象的值变为了“ab”呢,原因是 当a1+“b”时,虚拟机会在堆内存再创建一个String对象,同时将“ab”赋给这个对象,然后再让a1这个引用指向这个新创建的String对象,这样,我们就能达到字符串拼接的效果。

在这个地方,我们就明白了当我们需要进行大量的字符串拼接的时候,如果我们直接使用上面的直接相加的方法,那么会导致堆内存中存在大量的不必要的String对象,这显然是不太好的,因此我们引入了StringBuilder这个类,这个类中的字符数组没有被final所修饰,所以他可以不断地修改其中的值,当进行字符串拼接时,我们使用这个类就可以避免创建大量的对象,以减少内存的开销。

String的hash值

/** Cache the hash code for the string */

private int hash; // Default to 0

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;

}

从这部分源码我们可以看出,String的hashcode值是只和String所存入的字符串的值相关的,那么我们可以得出结论,即当引用从String对象中所获取的字符串的值相同时,无论这两个引用所指向的对象是否是同一个String对象,他们的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的equals方法,通过源码我们也发现当字符数组中存放的值相同时,equals方法会返回true,那么我们可以利用这个方法或者上面的hashcode方法来判断String对象所存储的值是否相同。

判断是否是同一个对象

当我们需要判断两个引用是否是指向同一个String对象时,用“ == ”即可。

String的几种创建方式及其实现原理

说完上述一些常用方法后,我们来看看下面的这几种String对象创建情况

String a1 = new String("abc");

String a2 = "abc";

String a3 = "abc";

String a4 = new String("abc");

System.out.println(a1==a2);

System.out.println(a2==a3);

System.out.println(a1==a4);

false

true

false

通过上面的实验我们可以看到,a2与a3通过直接用等号赋值的方式传递同样的值,他们所指向的对象都为同一个对象,然而当我们通过使用new String()这种方式赋给同样的值时,我们发现,这些引用所指向的对象不是同一个对象。那么,这种现象是如何产生的呢?下面我们就来说说String对象的多种创建方式的区别。

当我们执行`String a1 = new String("abc");`时,JVM会首先查找方法区的常量池是否存在存放“abc”的地址,如果没有,那么则会创建两个对象,一个是new String()创建出来的存在于堆中的对象,另一个对象会将自己的地址放到常量池中,如果有,则只会创建一个对象,即new String()创建出来的存在于堆中的对象。

当执行`String a2 = "abc";`时,a2同样会去常量池中寻找是否存在存放“abc”的地址,如果有,则直接指向这个地址,如果没有,那么它会创建一个对象并将自己的地址放到常量池中,当下次再执行`String a3 = "abc";`时,a3去常量池寻找则会发现存在存放“abc”的地址,此时a3会与a2相同,都指向同一个“abc”对象。

如此我们就可以很好的解释上面几行代码运行的结果了。

String的一些方法

public boolean equals(Object anObject) 判断字符串是否一样

public boolean equalsIgnoreCase(String anotherString) 判断字符串是否一样,忽略大小写

public boolean contains(CharSequence s) 判断字符串是否包含哪字符串

public boolean startsWith(String prefix) 判断字符串是否以什么开头

public boolean endsWith(String suffix) 判断字符串是否以什么结尾

public boolean isEmpty() 判断字符串是否为空字符串

int length():获取字符串的长度

char charAt(int index):获取指定索引位置的字符

int indexOf(int ch):获取指定字符在此字符串第一次出现处的索引

int indexOf(String str):返回指定字符串在此字符串中第一次出现处的索引

int indexOf(int ch,int fromIndex):返回指定字符在此字符串中指定位置后第一次出现处的索引

int indexOf(String str,int fromIndex):返回指定字符串在此字符串中指定位置后第一次出现处的索引

lastIndexOf() 最后出现的位置

String substring(int start):从指定位置开始截取字符串,默认到未尾

String substring(int start,int end):从指定位置开始到指定位置结束截取字符图


JDK对String常量池进行了修改

JDK1.6中常量池放在方法区中,JDK1.7中JVM把String常量区从方法区中移除了,它将常量池移到了堆中;JDK1.8中JVM把String常量池放入到了元空间,这是一个与堆内存不相连的内存空间。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容