String ww ="hello world"; String ww1 = "hello"+new String(" world"); String ww2 = "hello world"; String ww3 = "hello"+" world"; System.out.println(ww.equals(ww1)); System.out.println(ww==ww1); System.out.println(ww==ww2); System.out.println(ww==ww3);
true false true true
谁能告诉我第二个为什么是false??
-------------------------------------------------------------------------------------------------------
华丽的分割线
-------------------------------------------------------------------------------------------------------
百度了一天,我大致总结一下:
Java内存分配:
1. 寄存器:我们在程序中无法控制
2. 栈:存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中
3. 堆:存放用new产生的数据
4. 静态域:存放在对象中用static定义的静态成员
5. 常量池:存放常量
6. 非RAM(随机存取存储器)存储:硬盘等永久存储空间
String是一个特殊的包装类数据。可以用:
String ww ="hello world"; String ww1 = new String("hello world");
两种的形式来创建,第一种是用new()来新建对象的,它会在存放于堆中。每调用一次就会创建一个新的对象。
而第二种是先在栈中创建一个对String类的对象引用变量str,然后通过符号引用去字符串常量池里找有没有"hello world",如果没有,则将"hello world"存放进字符串常量池,并令str指向”hello world”,如果已经有”hello world” 则直接令str指向“hello world”。
最烦就是这个不太理解
String ww ="hello world"; String ww1 = "hello"+new String(" world");
ww 还是常量池中"hello world”的引用,ww1因为后半部分 new String(” world”)无法在编译期确定,所以也是一个新创建对象”hello world””的引用,这是网上的说法
后面我找到javap -c 命令查看java真正生成的指令,目前没找到汇编代码:
java指令java指令
public static void main(java.lang.String[]); Code: 0: ldc #16 // String hello world 2: astore_1 3: new #18 // class java/lang/StringBuilder 6: dup 7: ldc #20 // String hello 9: invokespecial #22 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V 12: new #25 // class java/lang/String 15: dup 16: ldc #27 // String world 18: invokespecial #29 // Method java/lang/String."<init>":(Ljava/lang/String;)V 21: invokevirtual #30 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 24: invokevirtual #34 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 27: astore_2 28: return }
ldc
将int, float或String型常量值从常量池中推送至栈顶
String ww ="hello world";
所以这个是放在常量池中的
其余的操作我YY下啊
先是从常量池中取出 "hello",然后创建一个StringBuilder,把hello作为参数放里面
StringBuilder sb = new StringBuilder("hello");
然后从常量池中取出 " world",赋值给一个String对面,
String new = new String(" world");
然后sb.append(new);
String ww1= sb.toString();
所以ww1是一个String对面的引用和ww常量池中的引用是不一样的
终于明白了,然并卵,面试失败