java String(常量池)浅析
java变量是不可修改变量,也不能被继承
测试题
String s1 = "a"; String s2 = "b"; String s3 = "a" + "b"; String s4 = s1 + s2; String s5 = "ab"; String s6 = s4.intern(); //问题 System.out.println(s3 == s4); //false System.out.println(s3 == s5); //true System.out.println(s3 == s6); //true String x2 = new String("c") + new String("d"); //new String("cd") 堆中 String x1 = "cd"; x2.intern(); //问,如果调换了最后两行代码的位置呢?如果是 jdk1.6 呢 System.out.println(x1 == x2); //false //最后两行调换 返回 true (x2 的对象引用会入堆) //最后两行调换,并且jdk1.6 返回 false (将x2 的副本入池)
一、字符串常量池
-
常量池的设计意图
jvm为提高性能和减少内存开销
1、创建了字符串常量池,类似于缓冲区,使用 string s1 = “xxxxx”时,如果常量池存在该字符串,那么将字符串返回给s1
2、若此时常量池不存在该字符串,在堆中创建字符串对象(实例化该字符串并将其放入常量池中)
-
字符串常量池的位置
字符串常量池存在方法区中
-
字符串常量池存放的东西
字符串常量池中存的是该字符串的引用
二、String s1 = new String(“小聪聪“)和 String s1 = ”小蚊子在此“的区别
- 使用new关键字时,该字符串一定会在堆中创建对象
- 使用字符串字面量时,先查看常量池中是否有该字符串,有则直接返回,没有则创建后写入常量池并返回
三、 string.intern()方法
-
jdk1.8
- string.intern() 方法返回java字符串在常量池中的引用,如果常量池中存在该字符串,直接返回该引用,否则将该对象添加到字符串常量池中,返回该引用
-
jdk1.6
- 将这个字符串对象尝试放入串池,如果有则不会放入,如果没有会把此对象复制一份,放入串池,并把串池中的对象返回
四、字符串拼接的实现
-
使用+拼接
使用java拼接时,java其实是生成了一个StringBuilder对象,然后将使用StringBuilder.append方法将两个字符串拼接起来
例如:
String s1 = "hello" + "world";
相当于
new StringBuilder("hello").append("world");
返回
new StringBuilder("hello").append("world").toString();
-
常量拼接和变量拼接
-
常量拼接
-
String s = "a" + "b";
-
在这种情况下编译期会进行优化(因为结果在编译期间确定为“ab”了),编译器会直接到常量池找值为“ab”的对象
- 找到了的话直接沿用常量池的对象
- 否则按照字面的模式创建字符串
-
-
变量拼接
-
String s = s1 + s2;
-
new StringBuilder().append(“a”).append(“b”).toString() new String(“ab”);
-
五、String、stringBuffer、StringBuilder
- String不可变类型
- StringBuffer是线程安全类型
- StringBuilder是线程不安全类型,在单线程下使用较为高效
未完待续
1、