String、StringBuffer、StringBuilder区别

String

我们都知道 Java 中的 String 类的设计是不可变的,来看下 String 类的源码。

      可以看出 String 类是 final 类型的,String 不能被继承。其值 value 也就是对字符数组的封装,即 char[],其值被定义成 private final 的,说明不能通过外界修改,即不可变。

来看下面例子:

运行结果示意图

都是String a 但是值变了,这其实是一个误区,从上面看 String 的结构可以得知字符串是由字符数组构成的,a只是一个引用而已,第一次引用了 "Java",后面变成了 "test",而 substring 也是用 Arrays.copyOfRange 方法重新复制字符数组构造了一个新的字符串,所以说,这里的字符串并不是可变,只是变更了字符串引用。

\color{green}{一般情况String确实不可变,可是二般情况呢?}

运行结果

     通过反射,我们改变了底层的字符数组的值,实现了字符串的 “不可变” 性,这是一种骚操作,不建议这么使用,违反了 Java 对 String 类的不可变设计原则,会造成一些安全问题,但由此看出String也不是百分百不变的。

\color{green}{通过字符串的两种创建方式来了解==和equals区别}

第一种:  String  a = "wang";

第二种:  String  b = new   String("wang");

案例如下:

运行结果示意图

         用" "创建的a,c两个字符串,==和equals比较返回都为true,这是因为a,b都指向了方法区的同一个字符串。所以,当同样的一个字符串用" "重复创建时只在方法区创建一次。

        用new创建的b,d两个字符串,equals为true很简单因为equals永远比较的是值,而==为false说明两个字符串的引用不一样。用new创建的字符串每次都会在JVM堆中创建,所以c,d都对应堆中的两个不同的字符串。


\color{green}{String的substring()方法}\color{red}{-截取字符串}

substring返回的是字符串索引位置beginIndex开始,endIndex-1结束的字符串。这个方法在jdk6,7是有差异的。

String背后是由char数组构成的,在JDK6中,String包含三个字段:char value[],      int offset,    int count,意思很简单。

JDK6
JDK7

输出:c

JDK8

我用的JDK8,划线部分可以看出,这其实是新建了一个字符串

\color{green}{String的intern()方法}\color{red}{-判断常量池是否有某个字符串}

intern的返回值就是该常量在常量池中的地址

其实在 jdk1.7 之前(这里的运行环境是1.8),第一个是false的。那么是什么导致的呢?答案就是这个intern的实现方式。

        在jdk1.7之前的版本,调用这个方法的时候,会去常量池中查看是否已经存在这个常量了,如果已经存在,那么直接返回这个常量在常量池中的地址值,如果不存在,则在常量池中创建一个,并返回其地址值。在JDK8中intern检测到这个常量在常量池中不存在的时候,不会直接在常量池中创建该对象了,而是将堆中的这个对象的引用直接存到常量池中,减少内存开销。

如果我们将第6行代码和第7行代码的顺序调换:

   这个时候在str1.intern()的时候 ,常量池中已经存在了str2这个常量,直接把str2的引用赋值给str1.intern()。而第一个是把str1的堆内存引用赋值给了str2,因此str1 = = str2的。

\color{green}{字符串拼接+ 和  concat}\color{red}{-字符串的拼接}

+详解

Java字符串在+的时候做了什么?

1.    生成class文件 javac   StringInternTest.java

2.    反编译class文件  javap  -verbose  -p  StringInternTest.class

从上面红色部分可以看出常量池中会有wang  、hongxing  、wanghongxing

在这里我们可以清楚的看见+其实本质上是调用了StringBuilder的append方法。所以

 str1 +"hongxing" = new StringBuilder.append(str1).append("hongxing")

既然是\color{red}{new}出来的对象,因此str2是存在了堆中的。

因此上面的.equals()是true而==是false

concat()方法

由以上例子可以得出结论

+可以是字符串或者数字及其他基本类型数据,而concat只能接收字符串。

+左右可以为null,concat为会空指针。


可变字符串StringBuffer 和 StringBuilder 的 3 个区别

区别1:线程安全

StringBuilder的toString()方法
StringBuffer的toString()方法

      StringBuffer:线程安全,StringBuilder:线程不安全。因为 StringBuffer 的所有公开方法都是 synchronized 修饰的,而 StringBuilder 并没有 StringBuilder 修饰。

区别2:缓冲区

       可以看出,StringBuffer 每次获取 toString 都会直接使用缓存区的 toStringCache 值来构造一个字符串。而 StringBuilder 则每次都需要复制一次字符数组,再构造一个字符串。所以,缓存冲这也是对 StringBuffer 的一个优化吧,不过 StringBuffer 的这个toString 方法仍然是同步的。


额外:

一般考察Java基础的时候,大多数会有== 和 equest()方法的区别,遇到这个知识点呢,大家把它分成两种类型来看就好了,分别是字符串

数字(Integer和int)

因为自动拆箱功能,Integer和int比较、int和new  Integer比较就是int和int比较。

equest()方法好理解,就是判断两个值是否相等,接下来我们判断==情况

解释:因为 Integer变量 指向的是 java 常量池 中的对象(int对象也是,这也是第一句话的原因,只要值相等,true,true,true), 而 new Integer() 的变量指向 堆中 新建的对象,两者在内存中的地址不同.

 Integer  =  150这句话会被 编译成Integer.valueOf(150),由于不在缓存-128-127之间,那么它本质就是调用new出来的

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

推荐阅读更多精彩内容