第三篇文章主要讲解相关“ equals 与 == ”面试题分析,分为以下部分:
- String类的“ equals 与 == ”
- Integer类的“ equals 与 == ”
String类的“ equals 与 == ”
在Java中对于字符串的创建,有两种形式:字符串常量和使用 new 来构造一个 String 对象。
字面量形式
在JVM中,为了减少对字符串变量的重复创建,其拥有一段特殊的内存空间,这段内存被称为字符串常量池。
比如 String str1 = "Hello"
创建了一个对象。此时默认字符串常量池中没有内容为“Hello”的对象存在。当JVM在字符串常量池中没有找到内容为 "Hello" 的对象时,就会创建一个内容为 "Hello" 的对象,并将它的引用返回给变量a。
当我们再次 String str2 = "Hello"
时,会发生什么情况呢?
首先JVM会在字符串常量池中查询是否有内容为 "Hello" 的对象。因为此时字符串常量池中已经有内容为 "Hello" 的对象了,故JVM不会创建新的地址空间,而是将原有的 "Hello" 对象的引用返回,所以此时变量 num1 和变量 num2 拥有的是同一个对象引用,即指向的是同一块内存地址。
使用 new 构造 String 对象
当我们 new 一个字符串对象时,不管字符串常量池中是否有内容相同的对象,JVM 都会创造一个新的对象,其内存地址均不同。
String str = new String("Hello")
创建过程分析:当执行String str = new String("Hello")
;时,JVM 首先在字符串常量池中查看是否存在字符串对象 "Hello",
- 如果不存在该对象,则先在字符串常量池中创建一个新的字符串对象"Hello",然后执行
new String("Hello")
构造方法,在堆内存中创建一个新的字符串对象"Hello",并将引用 str 指向堆内存中创建的新对象; - 如果已存在该对象,则不用创建新的字符串对象"Hello",而直接使用字符串常量池中已存在的对象"Hello", 然后执行
new String("Hello")
构造方法,在堆内存里创建一个新的字符串对象 "Hello",并将引用 str 指向堆内存中创建的新对象。
测试代码:
public class EqualsTest {
/**
* @param args
*/
public static void main(String[] args) {
String str1 = new String("Hello");
String str2 = new String("Hello");
String str3 = "Hello";
String str4 = "Hel" + "lo";
System.out.println("====== String equals ======");
System.out.println("str1 == str2 : " + (str1 == str2));
System.out.println("str1 == str3 : " + (str1 == str3));
System.out.println("str1.equals(str2) : " + str1.equals(str2));
System.out.println("str1.equals(str3) : " + str1.equals(str3));
System.out.println("str1 == str4 : " + (str1 == str4));
System.out.println("str1.equals(str4) : " + str1.equals(str4));
}
}
测试结果:
====== String equals ======
str1 == str2 : false
str1 == str3 : false
str1.equals(str2) : true
str1.equals(str3) : true
str1 == str4 : false
str1.equals(str4) : true
Integer 类的“ equals 与 == ”
自动装箱与自动拆箱
自动装箱:将Java的基本类型转换成包装器类型
自动拆箱:将Java的包装器类型转换成基本类型
Java数据类型分为基本数据类型和包装器类型。
基本类型: short int long float double byte boolean char
包装器类型: Short Integer Long Float Double Byte Boolean Character
Integer num = 1 // 自动装箱
Java调用 Integer 的 valueOf(int) 方法来完成自动装箱的
int num1 = num // 自动拆箱
Java调用 Integer 的 intValue 方法来完成自动拆箱的
注意:对于 Integer 类型的对象来说,如果我们要创建的 Integer 对象的数值在 [-128,127]的区间之内,缓存中早已存储了该范围的值,那么JVM就会在缓存中查找,返回已经存在的对象的引用;超过此范围,JVM需要重新创建该对象。
测试代码:
public class EqualsTest {
/**
* @param args
*/
public static void main(String[] args) {
int num1 = 1;
Integer num2 = 1;
Integer num3 = 1;
Integer num4 = 128;
Integer num5 = 128;
System.out.println("====== Integer equals ======");
System.out.println("num1 == num2 : " + (num1 == num2));
System.out.println("num2.equals(num1) : " + num2.equals(num1));
System.out.println("num2 == num3 : " + (num2 == num3));
System.out.println("num2.equals(num3) : " + num2.equals(num3));
System.out.println("num4 == num5 : " + (num4 == num5));
System.out.println("num4.equals(num5) : " + num4.equals(num5));
}
}
测试结果:
====== Integer equals ======
num1 == num2 : true
num2.equals(num1) : true
num2 == num3 : true
num2.equals(num3) : true
num4 == num5 : false
num4.equals(num5) : true