面试题1 - 什么情况下用+运算符进行字符串连接比调用StringBuffer/StringBuilder对象的append方法连接字符串性能更好?

面试题2 - 请说出下面程序的输出。

class StringEqualTest {

    public static void main(String[] args) {
String s1 = "Programming";
String s2 = new String("Programming");
String s3 = "Program";
String s4 = "ming";
String s5 = "Program" + "ming";
String s6 = s3 + s4;
System.out.println(s1 == s2);
System.out.println(s1 == s5);
System.out.println(s1 == s6);
System.out.println(s1 == s6.intern());
System.out.println(s2 == s2.intern());
}
}
返回值:
false
true
false
true
false

  今天在看面试题的时候注意到一个String的intern()方法,平常没用过,只是见过这个方法,也没去仔细看过这个方法。所以今天看了一下。个人觉得给String类中加入这个方法可能是为了提升一点点性能,因为从常量池取数据比从堆里面去数据要快一些。(个人感觉)

  API上的那几句关于这个方法,其实总结一句就是调用这个方法之后把字符串对象加入常量池中,常量池我们都知道他是存在于方法区的,他是方法区的一部分,而方法区是线程共享的,所以常量池也就是线程共享的,但是他并不是线程不安全的,他其实是线程安全的,他仅仅是让有相同值的引用指向同一个位置而已,如果引用值变化了,但是常量池中没有新的值,那么就会新开辟一个常量结果来交给新的引用,而并非像线程不同步那样,针对同一个对象,new出来的字符串和直接赋值给变量的字符串存放的位置是不一样的,前者是在堆里面,而后者在常量池里面,另外,在做字符串拼接操作,也就是字符串相"+"的时候,得出的结果是存在在常量池或者堆里面,这个是根据情况不同不一定的,我写了几行代码测试了一下。

  先上结果:

    1.直接定义字符串变量的时候赋值,如果表达式右边只有字符串常量,那么就是把变量存放在常量池里面。

    2.new出来的字符串是存放在堆里面。

    3.对字符串进行拼接操作,也就是做"+"运算的时候,分2中情况:

      i.表达式右边是纯字符串常量,那么存放在栈里面。

      ii.表达式右边如果存在字符串引用,也就是字符串对象的句柄,那么就存放在堆里面。

    String str1 = "aaa";
String str2 = "bbb";
String str3 = "aaabbb";
String str4 = str1 + str2;
String str5 = "aaa" + "bbb";
System.out.println(str3 == str4); // false
System.out.println(str3 == str4.intern()); // true
System.out.println(str3 == str5);// true

  结果:str1、str2、str3、str5都是存在于常量池,str4由于表达式右半边有引用类型,所以str4存在于堆内存,而str5表达式右边没有引用类型,是纯字符串常量,就存放在了常量池里面。其实Integer这种包装类型的-128 ~ +127也是存放在常量池里面,比如Integer i1 = 10;Integer i2 = 10; i1 == i2结果是true,估计也是为了性能优化。

学习了String类和StringBuffer类,现在从三分面来总结一下String、StringBuffer、StringBudder三者的区别:

  • 是否可变:

String:底层利用字符数组保存字符串常量,是不可变的,因为String类的原码中有:private final char value[];因为有final修饰,所以String类的对象是不可改变的。所以每次修String对象的值时,实际上是生成了一个新的对象,而指针指向了新的String对象;

StringBufferStringBudder底层是利用字符数组保存字符串变量的,在jdk1.7中它们都继承了AbstractStringBuilder类,而在AbstractStringBuilder类中有char[] value;,所以这两者对象是可变的;

  • 执行速度:一般情况StringBudder > StringBuffer > String

    String:因为String对象是不可变的,所以每次修String对象的时候,实际上是生成了一个新的对象,而指针指向了新的String对象;所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,那速度是一定会相当慢的。

    StringBuffer:而如果是使用 StringBuffer 类则结果就不一样了,每次结果都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,再改变对象引用。
    但是有特殊情况: String str = “abc” + “def”;StringBuffer Sb = new
    StringBuilder(“abc”).append(“
    def”);这时这种情况下:String的速度就要比StringBuffer的速度要快,因为这时jvm认为String str = “abc”
    + “def”;其实是:String str =
    “abcdef”;所以速度当然很快,这里说的是当String保存的字符串中有其他String的字符串时,速度就会变慢。

  • 是否线程安全:

    String: String中的对象是不可变的,也就可以理解为常量,显然线程安全。

    StringBuffer:是线程安全的,因为对方法加了同步锁或者对调用的方法加了同步锁,部分方法原码如下:

 public synchronized int length() {
return count;
} public synchronized int capacity() {
return value.length;
} public synchronized void ensureCapacity(int minimumCapacity) {
if (minimumCapacity > value.length) {
expandCapacity(minimumCapacity);
}
}

StringBudder:并没有对方法进行加同步锁,所以是非线程安全的。部分方法原码如下:

 private StringBuilder append(StringBuilder sb) {
if (sb == null)
return append("null");
int len = sb.length();
int newcount = count + len;
if (newcount > value.length)
expandCapacity(newcount);
sb.getChars(0, len, value, count);
count = newcount;
return this;
}
public StringBuilder delete(int start, int end) {
super.delete(start, end);
return this;
}
  • 对三者的使用意见:

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

java面试题----String、StringBuffer、StringBudder区别的更多相关文章

  1. Java学习之String StringBuffer StringBuilder区别

    1.String:对象长度是不可变的,是线程安全. 2.StringBuffer:对象长度是可变的,是线程安全. 3.StringBuilder:对象长度是可变,不是线程安全.

  2. 在JAVA中,String,Stringbuffer,StringBuilder 的区别

    首先是,String,StringBuffer的区别 两者的主要却别有两方面,第一是线程安全方面,第二是效率方面 线程安全方面: String  不是线程安全的,这意味着在不同线程共享一个String ...

  3. 【Java基础】String StringBuffer StringBuilder

    String String是不可变的 我们都知道String不是基本数据类型,而是一个对象,并且是final类型的,不可变的.(public final class String) 查看以下代码: S ...

  4. String,StringBuffer,StringBudilder区别--2019-04-13

    String,StringBuffer,StringBudilder区别: 1String 是字符串常量,创建内容不可以变, final修饰意味着String类型不能被继承,减少被修改的可能,从而最大 ...

  5. Android/Java 中的 String, StringBuffer, StringBuilder的区别和使用

    Android 中的 String, StringBuffer 和 StringBuilder 是移动手机开发中经常使用到的字符串类.做为基础知识是必须要理解的,这里做一些总结. A.区别 可以从以下 ...

  6. String,StringBuffer,StringBuilder区别

    String 字符串常量StringBuffer 字符串变量(线程安全)StringBuilder 字符串变量(非线程安全) 简要的说, String 类型和 StringBuffer 类型的主要性能 ...

  7. Java学习笔记--String StringBuffer StringBuilder

    String StringBuffer StringBuilder String http://docs.oracle.com/javase/7/docs/api/ 中文: http://www.cn ...

  8. 浅谈 Java 字符串(String, StringBuffer, StringBuilder)

    我们先要记住三者的特征: String 字符串常量 StringBuffer 字符串变量(线程安全) StringBuilder 字符串变量(非线程安全) 一.定义 查看 API 会发现,String ...

  9. 转:String StringBuffer StringBuilder区别

    转自:http://www.iteye.com/topic/522167 作者:每次上网冲杯Java时,都能看到关于String无休无止的争论.还是觉得有必要让这个讨厌又很可爱的String美眉,赤裸 ...

  10. 重温java中的String,StringBuffer,StringBuilder类

    不论什么一个系统在开发的过程中, 相信都不会缺少对字符串的处理. 在 java 语言中, 用来处理字符串的的类经常使用的有 3 个: String.StringBuffer.StringBuilder ...

随机推荐

  1. bytes和str之间的转换

    1.方法:decode解码(二进制转换成字符串) encode与上相反

  2. 格子刷油漆(dp)-----------蓝桥备战系列

    标题:格子刷油漆 X国的一段古城墙的顶端可以看成 2*N个格子组成的矩形(如图1所示),现需要把这些格子刷上保护漆. 你可以从任意一个格子刷起,刷完一格,可以移动到和它相邻的格子(对角相邻也算数),但 ...

  3. c++ 222

        [成功者的习惯]   1.背后说别人好话:听到某人说别人坏话时只微笑: 2.过去的事不全让人知道: 3. 尊敬不喜欢你的人:对事无情,对人有情: 4.多做自我批评:为别人喝彩: 5.感恩:学会 ...

  4. 怎样把ppt格式文件放到网页上?

    方法一:把ppt文件的扩展名直接修改为pps,嵌入到网页中嵌入代码:缺点:这种方式浏览器会提示是打开,还是下载,选择打开的话会直接在浏览器中打开,并且客户端一定要安装Office PowerPoint ...

  5. Jmeter4.0----HTTP Cookie管理器(9)

    1.说明 在脚本编写的过程中,我们常常会遇到用户登录之后的相关操作,但是又不想去通过脚本先模拟用户登录,再使用cookie值保持登录,做后续的操作的情况下,我们就会用到HTTP Cookie管理. H ...

  6. python_学生信息管理实例

    """提示:代码中的内容均被注释,请参考,切勿照搬""" """注意:代码切勿照搬,错误请留言指出" ...

  7. oracle 单实例DG(闪回技术四)

    一,flashback Oracle Flashback技术是一组数据库特性,它可以让你查看数据库对象的过去状态,或者将数据库对象返回到以前的状态,而无需使用基于时间点的介质恢复.根据数据库的变化,闪 ...

  8. mysql 配置文件详解

    mysql配置文件参数详解 (一) [client]port = 3306socket = /tmp/mysql.sock [mysqld]port = 3306socket = /tmp/mysql ...

  9. 牛客网Java刷题知识点之垃圾回收算法过程、哪些内存需要回收、被标记需要清除对象的自我救赎、对象将根据存活的时间被分为:年轻代、年老代(Old Generation)、永久代、垃圾回收器的分类

    不多说,直接上干货! 首先,大家要搞清楚,java里的内存是怎么分配的.详细见 牛客网Java刷题知识点之内存的划分(寄存器.本地方法区.方法区.栈内存和堆内存) 哪些内存需要回收 其实,一般是对堆内 ...

  10. mobile开发技巧(转)

    1.隐藏地址栏 很多文档介绍通过调用 window.scrollTo(0, 1); 就可以隐藏地址栏,但是通过实践发现隐藏地址栏还是真够坑爹的啊,只调用这一句话一般不会起作用,我们需要 functio ...