int a = 100;
Integer b = 100;
System.out.println(a==b); // true
String c = "123";
String d = new String("123");
System.out.println(c==d); // false
System.out.println(c.equals(d)); // true
但凡是使用 == 比较两个变量,一定是比较变量中存储的值
对于基本类型的变量来说比较值,对于引用类型的变量来说比较地址
基本数据类型的变量 中存储的是数值本身,引用类型的变量 中存储的是 地址
String 类重写后的 equals 会比较两个字符串的内容
1. int a = 100; 和 Integer b = 100;
int a = 100; // 基本类型
Integer b = 100; // 引用类型,自动装箱:Integer.valueOf( 100 )
System.out.println(a==b);
// a ==b ,b会发生自动拆箱:等价于 a ==b.intValue();
// 结果为:true,表示包装类类型的实例中封装的数值 与 基本类型变量中存储的数值 是相等的
2. String c=“123”;和String d=new String(“123”);
String c = "123"; // 变量 c 直接引用了 存放在 字符串常量 池 中的 String 实例 的地址
String d = new String("123"); // 变量 d 引用的是 在 堆内存中重新创建的 String 实例 的地址
System.out.println(c==d); // false ,两者被赋予的地址是不同的
区别:
-
String c = “123”;只需要在常量池中找是否有String实例 “123”,有就直接把地址赋给 栈中的c对象,没有则新创建 String实例 “123”;创建一个 c对象,并将其引用的地址值压入栈顶。相当于只创建了 1个 String实例。
-
String d = new String(“123”); 会在常量池中找是否有String实例 “123”,没有则要新创建 String实例 “123”;然后使用了new关键字,要在堆中为 d对象创建一个 String实例(从常量池中复制刚刚找到或创建的String实例 “123”);创建一个 d对象,并将其引用的地址值压入栈顶。相当于总共创建了 2个 String实例。
结合下面的图来理解:
- 字符串 是 常量;它们的值在创建之后不能更改。字符串缓冲区支持可变的字符串。因为 String 对象是不可变的,所以可以共享。例如:
String str = "abc";
等效于:
byte data[] = {'97','98','99'}; // byte类型的数组里存储的{'97','98','99'},对应就是{'a','b','c'}
String str = new String(data);