Java String

作者: DjangoW | 来源:发表于2018-08-11 10:58 被阅读0次

String在JAVA中是以final修饰的char数组实现的,所以一旦创建了某个string,不可修改。而且String不能被继承(final)。

先来看第一个例子:

String b = "b";
String anotherB="b";
String newB = new String("b");
b == anotherB //true
b == newB //false

其中原委:

b在java加载class的时候会被放入方法区(Method Area)的常量池(Constant Pool)中,之后通过b赋值的变量都被当作constant,直接指向常量池中的内存地址,所以banotherB指向同一个地址。

new String("b")则创建了一个instance,JVM会在执行这条语句的时候(Runtime)在堆(Heap)中为其分配内存,所以和b指向的不是同一个地址。

第二个例子:

String s = "a";
for(int i =0; i < 10; i++)
    s+="a";

编译期间,上段代码会Compiler被优化成:

String s = "a";
for(int i =0; i < 10; i++){
    StringBuilder sb = new StringBuilder(s);
    sb.append("a");
    s=sb.toString();
}

创建了10个StringBuilder实例,所以在loop中不要用string进行操作,不然会在Heap中创建大量短生命周期的instance而加重GC的负担。

第三个例子:

String s = "a" + "b" +"c";

这条语句java创建了多少对象?

一个!因为Compiler会针对这种语句做优化,所以上述语句等价于 String s = "abc";其中abc被当作const处理,加载进jvm的时候放入方法区常量池,s指向该const的地址。所以s == "abc"是true。

另一个例子:

String a = "a";
String ab = a + "b";
System.out.println(ab == "ab"); //false

因为ab赋值中a是变量,编译器不会针对优化。

String VS. StringBuilder VS. StringBuffer

  • StringBuilder是可变的(mutable),非线程安全。

  • String是不可变的(immutable)

  • StringBuffer是可变的,而且线程安全(thread-safe),因为其内的方法都被synchronize关键字修饰,保证每次只有一个线程操作该对象。因为每次操作都要先加monitor锁,所以其效率要差于StringBuilder.

String 为什么设计成immutable的?

  1. literal很常用,设计成final在JVM加载.class类文件的时候会把字符串放到方法区的常量池中,相同的字符串共用同一个常量池地址。
  2. String设计成final的会保证hashCode()也不会改变,从而可以在String中缓存其计算的hash code,不必每次都重新计算。
  3. 如果String是mutable的话,其hashCode()计算的结果也会变,在作为key存取Map的话就会出问题:改变之后的string变量作为key检索不出之前存入的value

相关文章

网友评论

    本文标题:Java String

    本文链接:https://www.haomeiwen.com/subject/ryorbftx.html