public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash;
如果你有一定源码分析基础。这里一看就直知道再JDK8中,String维护的是一个char数组,由于实现了Comparable可以比较大小。
为什么要把这个拿出来说?常量池中存在大量的字符串,这里又不得不的讨论他的存在方式。
1、String的不变可性:
package com.jvm.stu;
public class Main {
String str = new String("good");
char[] ch = {'t','e','s','t'};
public static void main(String[] args) {
Main ma = new Main();
change(ma.str, ma.ch);
System.out.println(ma.str);
System.out.println(ma.ch);
ma.changeThis(ma.str, ma.ch);
System.out.println(ma.str);
System.out.println(ma.ch);
}
public static void change(String str, char[] ch){
str = "change";
ch[0] = 'B';
}
public void changeThis(String str, char[] ch){
this.str = "change";
this.ch[0] = 'B';
}
}
2、字串常量池中不会存在相同的字符串。
String的String Pool是一个固定大小Hashtable,默认长度60013(不同版本不一样),如果String Pool的String非常多,就会造成
Hash冲突,从而导致链表很长,进而导致调用String.intern时性能大幅度降低。
-XX:StringTableSize可以设置StringTable的长度。
字符串常量放在堆中,两种方式一种String str=“str”,一种是使用intern方法创建
字符串拼接:
只要其中有一个是变量,结果就在堆中。变量的拼接原理是StringBuilder
如果拼接使用intern,则主动将常量池中还没有的字符串对象放入池中,并返回地址。
这也是因此
str = str+"iii";
StringBuilder sb = new StringBuilder();
sb.append("iiii");
后者更快。因为前缀每次+都会创建一个StringBuilder并且返回时sb.toString()。效率大大降低了。
金典题目分析:
到底造了几个对象?
String str=new String("aa");
1、2个。字节码可以明显看出堆空间中new一个String对象,常量池中放入"aa".
String str= new String("a") + new String("b");
2、5个。字节码可以明显看出堆空间
1、Stringbuilder对象
2、new String(“a”)对象
3、常量池中的"a"
4、new String(“b”)对象
5、常量池中的"b"