1         String、StringBuilder和StringBuffer的区别

  String、StringBuilder、StringBuffer都可以用来保存字符串。如果是使用次数比较少的变量,三者皆可。如果存在大量的循环叠加调用。String循环累加字符串时,实际内部每循环一次就会new一个StringBuilder变量,然后调用StringBuilder的函数append去添加。所以会在堆上创建出很多个StringBuilder对象,造成很多垃圾。所以循环累加字符串时最好使用StringBuilder。StringBuilder和StringBuffer类似,只是StringBuffer是线程安全的。所以在多线程使用中,采用StringBuffer。StringBuilder比String的效率高,造成的内存垃圾少。StringBuffer效率和Stringbuilder效率差不多,StringBuffer是线程安全的。

String内部是通过char数组来保存数据的,类的操作方法substr、replace等都需要重新new一个新的char数组来保存,不会对原String对象产生影响。

String str1 = "hello world";这样定义的字符常量存储在常量池中,常量池中相同的字符串只有一个备份。在栈上创建的多个引用可以指向相同的常量,只能更改引用指向不同的常量,不能修改引用指向的常量值。

String str2 = new String("hello world");字符串对象是在堆区进行的,而在堆区进行对象生成的过程是不会去检测该对象是否已经存在的。

1.1  循环累加效率

1.1.1            String循环累加

String string = "";

for(int i=0;i<10000;i++)

{

string += "hello";

}

从下面反编译出的字节码文件可以很清楚地看出:从第8行开始到第35行是整个循环的执行过程,并且每次循环会new出一个StringBuilder对象,然后进行append操作,最后通过toString方法返回String对象。也就是说这个循环执行完毕new出了10000个对象,试想一下,如果这些对象没有被回收,会造成多大的内存资源浪费。从上面还可以看出:string+="hello"的操作事实上会自动被JVM优化成:

StringBuilder str = new StringBuilder(string);

str.append("hello");

str.toString();

1.1.2            StringBuilder循环累加

StringBuilder stringBuilder = new StringBuilder();

for(int i=0;i<10000;i++)

{

stringBuilder.append("hello");

}

for循环式从13行开始到27行结束,并且new操作只进行了一次,也就是说只生成了一个对象,append操作是在原有对象的基础上进行的。因此在循环了10000次之后,这段代码所占的资源要比String小得多。

1.1.3            StringBuffer循环累加

StringBuilder和StringBuffer类拥有的成员属性以及成员方法基本相同,区别是StringBuffer类的成员方法前面多了一个关键字:synchronized,不用多说,这个关键字是在多线程访问时起到安全保护作用的,也就是说StringBuffer是线程安全的。

1.2  性能测试

对三个类进行50000次循环累加性能测试。String 8998毫秒,StringBuilder 2毫秒,StringBuffer3毫秒。因为String需要多次new StringBuilder,所以需要消耗大量的时间和造成大量的内存垃圾。StringBuffer和StringBuilder差不多,因为StringBuffer线程安全,所以会比StringBuilder多1毫秒。当字符串相加操作或者改动较少的情况下,建议使用 String str="hello"这种形式;当字符串相加操作较多的情况下,建议使用StringBuilder,如果采用了多线程,则使用StringBuffer。

1.3  练习测试

(1)下面这段代码的输出结果是什么?

  String a = "hello2";   String b = "hello" + 2;   System.out.println((a == b));

  输出结果为:true。原因很简单,"hello"+2在编译期间就已经被优化成"hello2",因此在运行期间,变量a和变量b指向的是同一个对象。

(2)下面这段代码的输出结果是什么?

  String a = "hello2";    String b = "hello";       String c = b + 2;       System.out.println((a == c));

  输出结果为:false。由于有符号引用的存在,所以  String c = b + 2;不会在编译期间被优化,不会把b+2当做字面常量来处理的,因此这种方式生成的对象事实上是保存在堆上的。因此a和c指向的并不是同一个对象。javap -c得到的内容:

(3)下面这段代码的输出结果是什么?

  String a = "hello2";     final String b = "hello";       String c = b + 2;       System.out.println((a == c));

  输出结果为:true。对于被final修饰的变量,会在class文件常量池中保存一个副本,也就是说不会通过连接而进行访问,对final变量的访问在编译期间都会直接被替代为真实的值。那么String c = b + 2;在编译期间就会被优化成:String c = "hello" + 2; 下图是javap -c的内容:

  

总结:

对于String b=“hello”+2;这种常量相加,在编译期就优化为常量,在常量池保存。对于String b=a+2; 不会在编译期间被优化,不会把b+2当做字面常量来处理的,实际是存储在堆上面的,调用了一次new StringBuilder。

如果a的定义是final String a = "hello";     对于被final修饰的变量,会在class文件常量池中保存一个副本,也就是说不会通过连接而进行访问,对final变量的访问在编译期间都会直接被替代为真实的值。那么String b= a + 2;在编译期间就会被优化成:String b = "hello" + 2;

String a = "hello";String b =  new String("hello");String c =  new String("hello");String d = b.intern();String.intern方法的使用。在String类中,intern方法是一个本地方法,在JAVA SE6之前,intern方法会在运行时常量池中查找是否存在内容相同的字符串,如果存在则返回指向该字符串的引用,如果不存在,则会将该字符串入池,并返回一个指向该字符串的引用。因此,a和d指向的是同一个对象。

String、StringBuilder和StringBuffer的区别的更多相关文章

  1. String, StringBuilder 与StringBuffer的区别与联系

    1.区别 (1)String构建的对象不能改变,每次对String进行操作时,如两个String相加,需要新建一个String对象,然后容纳最终的结果. 而StringBuilder与StringBu ...

  2. String,StringBuilder与StringBuffer的区别

    相信大家看到过很多比较String和StringBuffer区别的文章,也明白这两者的区别,然而自从Java 5.0发布以后,我们的比较列表上将多出一个对象了,这就是StringBuilder类.St ...

  3. String详解, String和CharSequence区别, StringBuilder和StringBuffer的区别 (String系列之1)

    本章主要介绍String和CharSequence的区别,以及它们的API详细使用方法. 转载请注明出处:http://www.cnblogs.com/skywang12345/p/string01. ...

  4. String详解, String和CharSequence区别, StringBuilder和StringBuffer的区别

    本章主要介绍String和CharSequence的区别,以及它们的API详细使用方法. 转载请注明出处:http://www.cnblogs.com/skywang12345/p/string01. ...

  5. 面试必知:String、StringBuilder、StringBuffer的区别

    你知道String.StringBuilder.Stringbuffer的区别吗?当你创建字符串的时候,有考虑过该使用哪个吗? 别急,这篇文章带你解决这些问题. 可变性 首先,String是字符串,我 ...

  6. JAVA String介绍、常量池及String、StringBuilder和StringBuffer得区别. 以及8种基本类型的包装类和常量池得简单介绍

    一.概述 String是代表字符串的类,本身是一个最终类,使用final修饰,不能被继承. 二.定义方式   方式一:直接赋值法 String str1 = "hello"; 方式 ...

  7. StringBuilder与StringBuffer的区别

    相信大家看到过很多比较String和StringBuffer区别的文章,也明白这两者的区别,然而自从Java 5.0发布以后,我们的比较列表上将多出一个对象了,这就是StringBuilder类.St ...

  8. StringBuilder和StringBuffer的区别

    Java中StringBuilder和StringBuffer的区别分析 StringBUilder是线程不安全的(线程同步访问的时候会出问题),但是效率相对较高. (String类型使用加号进行拼接 ...

  9. Java基础(32):String与StringBuilder、StringBuffer的区别(String类)

    在Java中,除了可以使用 String 类来存储字符串,还可以使用 StringBuilder 类或 StringBuffer 类存储字符串,那么它们之间有什么区别呢? String 类具有是不可变 ...

随机推荐

  1. win 下 python ImportError: No module named requests

    第一次弄爬虫,报库找不到,网上找了半天,一般都让都让改成绝对路径...那不是饮鸩止渴嘛. 然后 在无意中发现,不需要控制台输入pip命令,因为不是在Linux下啊,,win下直接在pycharm里添加 ...

  2. Chrome Inspect调试微信出现空白页面的解决方法

    首先,需要打开手机的USB调试和微信的TBS 调试开关. 如果不打开TBS开关,Inspect时会检测不到任何微信的H5页面 使用微信扫码下方二维码,打开TBS调试开关: 普通网页: 小程序: 微信扫 ...

  3. 201808_summary

    @Consumes @Produces分别表示入参和出参数吗 可以这样讲.但是不是很到位.是限定作用,类似于filterconsumes: 指定处理请求的提交内容类型(Content-Type),例如 ...

  4. CF822D 贪心+递推

    CF822D [题目链接]CF822D [题目类型]贪心+递推 &题意: 给你n个人,你可以把他们分组,但必须保持每组相等,分组之后每2个人会比赛,比如一组有i个人,那么就要比赛 次,f[i] ...

  5. eslint的安装与使用

    什么是 ESLint ESLint(中文站点)是一个开源的 JavaScript 代码检查工具,使用 Node.js 编写,由 Nicholas C. Zakas 于 2013 年 6 月创建.ESL ...

  6. PHP、mySQL及Navicat安装·Mac

    PHP配置 Mac系统对开发人员非常友好,除了自带Apache外,还带有能与Apache相匹配的服务器端脚本语言PHP,因此,Mac中PHP的启动只需要在Apache服务中进行一下超级简单的配置即可直 ...

  7. 一般程序中的session

    在WebHandler中无法访问session: IRequiresSessionState必须实现这个接口(不包含任何方法的标记接口), 需要导入using System.Web.SessionSt ...

  8. Blender学习

    学习顺序(下面为引用他人的视频或博客) 51个必须知道的blender操作 https://www.bilibili.com/video/av4619930/ Blender常用快捷键一览表 http ...

  9. LearnOpenGL

    ---------------------------------------------- LearnOpenGL ----------------------------------------- ...

  10. CSS图形

    1.正方形 最终效果:   CSS代码如下: #square { width: 100px; height: 100px; background: red; }    2.长方形 最终效果:   CS ...