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. python 开发环境部署

    pip 通过google搜索到,2019.4月的版本是19. 需要更换源,否则会挺慢. Windows下更换pip源为清华源 打开appdata文件夹,在资源管理器的地址栏输入%appdata%后回车 ...

  2. Cocos Creator 按钮音效封装重写

    cc.Button.prototype._onTouchEnded = function (t) { cc.hb.audioMgr.playMusic("click", false ...

  3. Matlab文件和数据的导入与导出

    ref: https://blog.csdn.net/zengzeyu/article/details/72530596 Matlab文件和数据的导入与导出 2017年05月19日 15:18:35  ...

  4. FB面经 Prepare: K closest point to the origin

    Give n points on 2-D plane, find the K closest points to origin Based on bucket sort: package fbPrac ...

  5. java中进程与线程的区别

    进程是一个正在运行的应用程序.一个进程包含一个或多个线程.它可以是一段完整的代码或部分程序的动态执行.系统资源分配与调度的基本单位.而线程是CPU调度与运行的基本单位,它是一组指令的集合或是程序的特殊 ...

  6. js大图轮播和倒计时

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. PHP 程序员危机(转载)

    感谢有这样的机会,能和大家一起来聊聊开发者的那些事儿. 其实程序员危机是一个真实存在的问题.也有人说是互联网行业的下滑或者互联网行业已过了风口等等.我在这儿主要谈的是 PHP 程序员的危机,而这种危机 ...

  8. JavaFX-Platform&Screen

    1Platform常用方法有exit().runlater().isSupported() exit(): Stage stage = new Stage(); Stage stage1 = new ...

  9. CentOS7──xxx is not in the sudoers file

    提示"xxx is not in the sudoers file. This incident will be reported.其中 ”XXX“是你的用户名,也就是你的用户名没有权限使用 ...

  10. liunx驱动----按键中断

    liunx 中断 先设置异常入口 异常向量 void __init trap_init(void) 构造了异常向量 vector_irq+offset       按下按键: cpu自动进入异常模式 ...