1.String类声明是final的,不可以被继承。
2.String 创建对象问题
例题1
String n = "hello";
n = "haha";
这题创建了几个对象?
做着题之前 应先明白String创建对象的方式及内存布局图
(string就像是C语言中常说的字符串,字符串其实就是一个String类的对象。)
补充一点 判断 s == s2 返回false
s和s2的地址并不相同
再来看着题 首先池中没有hello 创建一个对象 然后也没有haha,在创建一个对象 而n指向haha ,(不是替换hello,hello没变)所以共创建了2个对象
例题2 创建了几个对象
String n = "hello" + "abc";
这里很多人会误以为创建了2个对象 一个hello一个abc ,编译器会做一个优化 实际上就创建了一个对象 helloabc
例题3
String a = "hello";
String b = "abc";
String c = a +b;
String d = "hello" + "abc";
这里关键是看String c = a + b;是怎么执行的 通过debug来查看
通过debug看 实际上就是在堆中创建了一个对象 指向helloabc,又因为hello和abc早已创建好了
所以helloabc就不要创建了 最后就是 a b c这三个
再加强上面的补充
c == d 这返回false和上面的一样
小结一下例题3:
c是变量相加,是在堆中。d是常量相加,看的是池。
例题4
下列程序运行的结果是什么,尝试画出内存布局图?
public class Test1 {
String str = new String("hsp");
final char[] ch = {'j', 'a', 'v', 'a'};
public void change(String str, char ch[]) {
str = "java"
ch[0] = 'h';
public static void main(String[] args) {
Test1 ex = new Test1();
ex.change(ex.str, ex.ch);
System.out.print(ex.str + "and ");
System.out.println(ex.ch);
}
这里一步步分析:
第一句 String str = new String("hsp");
在堆中创建一个名为str的对象 里面有一个value数组的地址 value保存着在常量池中hsp的地址(str指向value value指向常量池中的hsp)
第二句 final char[] ch = {'j', 'a', 'v', 'a'};
在堆中创建一个数组ch 指向一段空间(堆中)这段空间里有 java
第三句 Test1 ex = new Test1();
在栈中创建一个ex指向堆中的对象(包括 str 和ch)
第四句 ex.change(ex.str, ex.ch);
public void change(String str, char ch[]) {
str = "java"
ch[0] = 'h';
调用change方法 当调用方法时会调用一个新栈 当ex.str时 新栈中有一个str和堆中str指向相同指向value。然后进入change方法.执行 str = "java";此时 新栈中的str的指向变了 变成了常量池中的java(由hsp变成java).执行 ex.ch;时 新栈中的ch 指向堆中的数组(Java)。ch[0] = 'h';ch[0]由j变为了h;ex.change结束 新栈也消失
最后System.out.print(ex.str + "and ");
System.out.println(ex.ch);
前者输出 hspand 后者 hava
分析图:
总结
1.通过字面量定义的字符串存放在字符串常量池,通过new出来的字符串存放在堆空间
2.池和堆 内存布局图 String对象的创建 及String类不可变对象
2022.3.2