观察下列代码,分析结果()
String s1 = "coder"; String s2 = "coder"; String s3 = "coder" + s2; String s4 = "coder" + "coder"; String s5 = s1 + s2; System.out.println(s3 == s4); System.out.println(s3 == s5); System.out.println(s4 == "codercoder");
观察下列代码,分析结果()
String s1 = "coder"; String s2 = "coder"; String s3 = "coder" + s2; String s4 = "coder" + "coder"; String s5 = s1 + s2; System.out.println(s3 == s4); System.out.println(s3 == s5); System.out.println(s4 == "codercoder");
false;false; true;
false;true; true;
false;false; false;
true;false; true;
Java内存结构包含以下部分:
1、栈区:由编译器自动分配释放,具体方法执行结束后,系统自动释放JVM内存资源。
其作用有保存局部变量的值,包括:1.用来保存基本数据类型的值;2.保存类的实例,即堆区对象的引用。也可以用来保存加载方法时的帧。
2、堆区:一般由程序员分配释放,JVM不定时查看这个对象,如果没有引用指向这个对象就回收。
其作用为用来存放动态产生的数据,包括new出来的实例,字符数组等。
同一个类的对象拥有各自的成员变量,存储在各自的堆中,但是他们共享该类的方法。
3、数据区:用来存放static定义的静态成员。
public static void main(String args[]) { // 字符串常量,分配在常量池中,编译器会对其进行优化, Interned table // 即当一个字符串已经存在时,不再重复创建一个相同的对象,而是直接将s2也指向"hello". String s1 = "hello"; String s2 = "hello"; // new出来的对象,分配在heap中.s3与s4虽然它们指向的字符串内容是相同的,但是是两个不同的对象. // 因此==进行比较时,其所存的引用是不同的,故不会相等 String s3 = new String("world"); String s4 = new String("world"); System.out.println(s1 == s2); // true System.out.println(s3 == s4); // false System.out.println(s3.equals(s4)); // true // String中equals方法已经被重写过,比较的是内容是否相等. }
String s1 = "coder"; String s2 = "coder"; String s3 = "coder" + s2; String s4 = "coder" + "coder"; String s5 = s1 + s2; System.out.println(s3 == s4); System.out.println(s3 == s5); System.out.println(s4 == "codercoder");
// 字符串常量,分配在常量池中,编译器会对其进行优化, Interned table // 即当一个字符串已经存在时,不再重复创建一个相同的对象,而是直接将s2也指向"hello". String s1 = "hello"; String s2 = "hello";但是若是变量定义赋值,或者new,就会在内存中新找一段地址。
System.out.println(s3 == s4); //false System.out.println(s3 == s5); //false System.out.println(s4 == "codercoder"); //true
String s1 = "coder"; // 在字符串常量池中创建一个字符串"coder",s1指向它 String s2 = "coder"; // 在字符串常量池中找到已经存在的"coder",s2指向它,所以s1和s2指向同一个对象 String s3 = "coder" + s2; // 这里涉及到字符串的连接,会创建新的字符串对象,s3指向这个新的对象 String s4 = "coder" + "coder"; // 这里是常量字符串的连接,编译器会在编译期间就完成连接,所以s4指向字符串常量池中的"codercoder" String s5 = s1 + s2; // 这里也是字符串的连接,会创建新的字符串对象,s5指向这个新的对象 System.out.println(s3 == s4); // s3和s4指向的不是同一个对象,所以结果为false System.out.println(s3 == s5); // s3和s5指向的不是同一个对象,所以结果为false System.out.println(s4 == "codercoder"); // s4和"codercoder"都指向字符串常量池中的同一个对象,所以结果为true
false false true
/**对class文件反编译 *在JVM中对String的优化 *采用字面量赋值时 如果+号两边不是变量,JVM会自动进行字符的拼接。 *如果+号两边有变量,JVM不会对这一行进行任何操作 **/ String a="codercoder"; String b="coder"; String c="coder"+"coder";//==>String c="codercoder"; String d="coder"+b;//==>String d=new String("coder"+b); //a==c a!=d
在两个String变量相加的时候,变量不是显式已知的(编译器不知),底层实际调用了StringBuffer的append方法,s3指向堆区而不是常量池。
在两个String字面量相加的时候,由于字面量是显式已知的,编译器将其优化为相加的结果并存入常量池。