11. ==和equals方法 & 常量池
一、使用==来判断两个变量是否相等
1. 如果两个变量是基本类型变量,且都是数值类型,则只要两个变量的值相等,就将返回true
2. 如果两个变量是引用类型变量,则只有它们指向同一个对象时,才返回true
// ex1:基本类型 int it = 65; float fl = 65.0f; char ch = 'A'; boolean bl1 = (it == fl); // true boolean bl2 = (it == ch); // true // ex2:引用类型 String str1 = new String("Hello"); String str2 = new String("Hello"); boolean bl3 = (str1 == str2); // false
注:str1和str2都是引用类型变量,它们分别指向两个通过new创建的String对象,因此它们不相等。
二、使用equals方法来判断两个变量是否相等
1. equals()是Object类提供的一个实例方法,因此所有引用变量都可调用该方法来判断是否与其他引用变量相等
2. Object类提供的equals()同样要求两个引用变量指向同一个对象时才返回true,因此各子类可重写该方法来实现所需的判断标准
- 如String类中已经重写了equals(),其判断标准是只要两个字符串所包含的字符序列相同,就返回true
// ex:使用String类重写的equals方法来判断 String str1 = new String("Hello"); String str2 = new String("Hello"); boolean bl = str1.equals(str2); // true
3. 正确地重写equals()应满足下列条件
- 自反性:对任意x,x.equals(x)一定返回true
- 对称性:对任意x和y,如果y.equals(x)返回true,则x.equals(y)也返回true
- 传递性:对任意x, y, z,如果x.equals(y)返回true,y.equals(z)返回true,则x.equals(z)一定返回true
- 一致性:对任意x和y,如果对象中用于等价比较的信息没有改变,那么无论调用x.equals(y)多少次,返回的结果应保持一致
- 对任何不是null的x,x.equals(null)一定返回false
三、常量池
1. 当Java程序直接使用形如"Hello"的字符串直接量(包括可以在编译时就计算出来的字符串值,如"Hel" + "lo")时,JVM将会使用常量池来管理这些字符串
2. 当Java程序使用new String("Hello")时,JVM会先使用常量池来管理"Hello"直接量,再调用String类的构造器来创建一个新的String对象,新创建的String对象被保存在堆内存中,换句话说,new String("Hello")一共产生了两个字符串对象
常量池专门用于管理在编译时被确定并被保存在已编译的.class文件中的一些数据,它包括了关于类、方法、接口中的常量,还包括字符串常量。
// s1直接引用常量池中的"我爱China" String s1 = "我爱China"; String s2 = "我爱"; String s3 = "China"; // s4后面的字符串值可以在编译时就确定下来 // s4直接引用常量池中的"我爱China" String s4 = "我爱" + "China"; // s5和s4是一样的 String s5 = "我" + "爱" + "China"; // s6后面的字符串值不能在编译时就确定下来 // s6不能引用常量池中的"我爱China" String s6 = s2 + s3; // 使用new调用构造器将会创建一个新的String对象 // s7引用堆内存中新创建的String对象 String s7 = new String("我爱China"); boolean bl1 = (s1 == s4); // true boolean bl2 = (s1 == s5); // true boolean bl3 = (s1 == s6); // false boolean bl4 = (s1 == s7); // false
- JVM常量池保证相同的字符串直接量只有一个,不会产生多个副本,因此s1、s4、s5都将引用常量池中的同一个字符串对象
- 使用new String()创建的字符串对象是运行时创建出来的,它被保存在运行时内存区(即堆内存)内,不会放入常量池中