1. 输出结果为 true,"hello" + 1 在编译期间就被优化成了 "hello1",因此在运行期间,变量 a 和变量 b 指向的是同一个对象
String a = "hello1"; String b = "hello" + 1; System.out.println(a == b);
2. 输出结果为 false,由于有符号引用的存在,所以 String c = b + 2; 不会再编译期间被优化,不会当做字面量来处理。只有在程序运行期间动态分配并将连接后的新地址赋给 c
String a = "hello2"; String b = "hello"; String c = b + 2; System.out.println((a == c));
3. 输出结果为:true,对于被 final 修饰的变量,它在编译时被解析为常量值得一个本地拷贝存储到自己的常量池或嵌入到它的字节码中。对 final 变量修饰的访问在编译期间都会被替代为真实的值。
String a = "hello2"; final String b = "hello"; String c = b + 2; System.out.println((a == c));
4. 虽然 b 被 final 修饰,但是由于其赋值是通过方法调用返回的,那么它的值只能在运行期间确定,因此 a 和 c 指向的不是同一个对象
public class Main { public static void main(String[] args) { String a = "hello2"; final String b = getHello(); String c = b + 2; System.out.println((a == c)); } public static String getHello() { return "hello"; } }
6. 在 String 类中,intern 方法是一个本地方法,会在运行时常量池中查找是否存在相同内容的字符串,如果存在则返回指向该字符串的引用,如果不存在,则会将该字符串入池,并返回一个指向该字符串的引用,因此指向的是同一个对象。
public class Main { public static void main(String[] args) { String a = "hello"; String b = new String("hello"); String c = new String("hello"); String d = b.intern(); System.out.println(a==b); System.out.println(b==c); System.out.println(b==d); System.out.println(a==d); } }
false false false true
6. final 只对引用的值(即内存地址)有效,迫使引用指向初始指向的对象,改变指向会导致编译期错误,至于所指向的对象的变化,final 是不负责的
final StringBuffer a = new StringBuffer("111"); final StringBuffer b = new StringBuffer("222"); a=b;//此句编译不通过 final StringBuffer a = new StringBuffer("111"); a.append("222");//编译通过