博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
String StringBuilder StringBuffer
阅读量:6945 次
发布时间:2019-06-27

本文共 3403 字,大约阅读时间需要 11 分钟。

  hot3.png

        开门见山  :  String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且大量浪费有限的内存空间,StringBuffer是可变类,和线程安全的字符串操作类,任何对它指向的字符串的操作都不会产生新的对象,StringBuffer和StringBuilder类功能基本相似

1.   String 类 

  String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且大量浪费有限的内存空间。 
String a = "a"; //假设a指向地址0x0001 
a = "b";//重新赋值后a指向地址0x0002,但0x0001地址中保存的"a"依旧存在,但已经不再是a所指向的,a 已经指向了其它地址。 
因此String的操作都是改变赋值地址而不是改变值操作。 

String类其实是通过char数组来保存字符串的.

String对象的任何改变都不影响到原对象,相关的任何change操作都会生成新的对象

2.

StringBuffer是可变类,和线程安全的字符串操作类,任何对它指向的字符串的操作都不会产生新的对象。 每个StringBuffer对象都有一定的缓冲区容量,当字符串大小没有超过容量时,不会分配新的容量,当字符串大小超过容量时,会自动增加容量。 

StringBuffer buf=new StringBuffer(); //分配长16字节的字符缓冲区 
StringBuffer buf=new StringBuffer(512); //分配长512字节的字符缓冲区 
StringBuffer buf=new StringBuffer("this is a test")//在缓冲区中存放了字符串,并在后面预留了16字节的空缓冲区。 
3.StringBuffer 
  StringBuffer和StringBuilder类功能基本相似,主要区别在于StringBuffer类的方法是多线程、安全的,而StringBuilder不是线程安全的,相比而言,StringBuilder类会略微快一点。对于经常要改变值的字符串应该使用StringBuffer和StringBuilder类。 

4.线程安全 

StringBuffer 线程安全 
StringBuilder 线程不安全 
5.速度 
一般情况下,速度从快到慢:StringBuilder>StringBuffer>String,这种比较是相对的,不是绝对的。 

比如String str = "hello"+ "world"的效率就比 

StringBuilder st  = new StringBuilder().append("hello").append("world")要高。

因此,这三个类是各有利弊,应当根据不同的情况来进行选择使用:

  当字符串相加操作或者改动较少的情况下,建议使用 String str="hello"这种形式;

        字符串相加操作较多的情况下,建议使用StringBuilder,如果采用了多线程,则使用StringBuffer

6.总结 

            (1).如果要操作少量的数据用 = String 
            (2).单线程操作字符串缓冲区 下操作大量数据 = StringBuilder 
            (3).多线程操作字符串缓冲区 下操作大量数据 = StringBuffer

常见的关于String、StringBuffer的面试题

    

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当做字面常量来处理的,因此这种方式生成的对象事实上是保存在堆上的。

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; 

4.下面这段代码输出结果为:

public class Main {    public static void main(String[] args) {        String a = "hello2";        final String b = getHello();        String c = b + 2;        System.out.println((a == c));    }          public static String getHello() {        return "hello";    }}

输出结果为false。这里面虽然将bfinal修饰了,但是由于其赋值是通过方法调用返回的,那么它的值只能在运行期间确定,因此ac指向的不是同一个对象。

5.

Strign a= “hello”;String b= new String (“hello”);String d = b.intern();System.out.println(a==d);//输入true;

这里面涉及到的是String.intern方法的使用。在String类中,intern方法是一个本地方法,在JAVA SE6之前,intern方法会在运行时常量池中查找是否存在内容相同的字符串,如果存在则返回指向该字符串的引用,如果不存在,则会将该字符串入池,并返回一个指向该字符串的引用。因此,ad指向的是同一个对象。

 

String str = new String("abc")创建了多少个对象?

这段代码在运行期间确实只创建了一个对象,即在堆上创建了"abc"对象。而为什么大家都在说是2个对象呢,这里面要澄清一个概念  该段代码执行过程和类的加载过程是有区别的。在类加载的过程中,确实在运行时常量池中创建了一个"abc"对象,而在代码执行过程中确实只创建了一个String对象。

  因此,这个问题如果换成 String str = new String("abc")涉及到几个String对象?合理的解释是2个。

  个人觉得在面试的时候如果遇到这个问题,可以向面试官询问清楚是这段代码执行过程中创建了多少个对象还是涉及到多少个对象再根据具体的来进行回答。

public class Main {    public static void main(String[] args) {        String str1 = "I";        //str1 += "love"+"java";        1)        str1 = str1+"love"+"java";      //2)       /*       /*和2)的区别        1比2 效率高,1在编译时会被优化.而2不会*/*/       }}

        参考文章:

                        http://www.cnblogs.com/dolphin0520/p/3778589.html

转载于:https://my.oschina.net/dadou/blog/482502

你可能感兴趣的文章
vim 学习方法
查看>>
Extamil+postfix web页面管理发送虚拟账号邮件
查看>>
《设计模式系列》---模板方法
查看>>
Facebook推出应用中心 划定主要合作伙伴
查看>>
Runtime.addShutdownHook()(译)
查看>>
yum安装(本地yum源&网络yum源)
查看>>
【209期推荐】HIS实施的尴尬,你到底这是要闹哪样啊?
查看>>
nginx 伪静态 rewrite
查看>>
分布式文件系统之MogileFS
查看>>
每日备份数据的脚本
查看>>
linux下vi命令
查看>>
常用的开源工具总结
查看>>
Citrix XenDesktop桌面登录VM提示Citrix Web插件错误
查看>>
centos 编译安装 python
查看>>
关于 获取 Android 本地手机 号码
查看>>
SpringCloud系列第01节之入门
查看>>
Android Framework 分析---3PackageManager 分析
查看>>
android权限大全
查看>>
SQLite数据库-execSQL()和rawQuery()方法
查看>>
View事件分发机制
查看>>