Skip to main content

java中equal()方法和==的区别是什么

5 min read

==与equals的主要区别是:

  • ==常用于比较原生类型,而equals()方法用于检查对象的相等性。
  • 如果==和equals()用于比较对象,当两个引用地址相同,==返回true。而equals()可以返回true或者false主要取决于重写实现。

最常见的一个例子,字符串的比较,不同情况==和equals()返回不同的结果。

equals()方法最重要的一点是,能够根据业务要求去重写,按照自定义规则去判断两个对象是否相等。

重写equals()方法的时候,要注意一下hashCode是否会因为对象的属性改变而改变,否则在使用散列集合储存该对象的时候会碰到坑!!理解equals()方法的存在是很重要的。

1.1.1 字符串字面量比较

String s1 = "hello";
String s2 = "hello";
String s3 = "he" + "llo";

System.out.println(s1 == s2); // true - 指向字符串常量池的同一个对象
System.out.println(s1 == s3); // true - 编译期优化,同样指向常量池
System.out.println(s1.equals(s2)); // true - 内容相同
System.out.println(s1.equals(s3)); // true - 内容相同

1.1.2 new String() 创建对象

String s1 = "hello";
String s2 = new String("hello");
String s3 = new String("hello");

System.out.println(s1 == s2); // false - s1在常量池,s2在堆内存
System.out.println(s2 == s3); // false - 两个不同的堆内存对象
System.out.println(s1.equals(s2)); // true - 内容相同
System.out.println(s2.equals(s3)); // true - 内容相同

1.1.3 运行时拼接的字符串

String s1 = "hello";
String s2 = "he";
String s3 = s2 + "llo"; // 运行时拼接

System.out.println(s1 == s3); // false - s3在堆内存中
System.out.println(s1.equals(s3)); // true - 内容相同

1.1.4 intern() 方法的影响

String s1 = "hello";
String s2 = new String("hello");
String s3 = s2.intern(); // 将s2放入常量池

System.out.println(s1 == s2); // false
System.out.println(s1 == s3); // true - intern()后指向同一个常量池对象
System.out.println(s1.equals(s2)); // true

1.1.5 更复杂的例子

String s1 = "java";
String s2 = "ja";
String s3 = "va";
String s4 = s2 + s3; // 运行时拼接
String s5 = "ja" + "va"; // 编译期优化
final String s6 = "ja";
String s7 = s6 + "va"; // 编译期优化(s6是final)

System.out.println(s1 == s4); // false
System.out.println(s1 == s5); // true
System.out.println(s1 == s7); // true
System.out.println(s1.equals(s4)); // true

1.1.6 空字符串和null的比较

String s1 = "";
String s2 = new String("");
String s3 = null;

System.out.println(s1 == s2); // false
System.out.println(s1.equals(s2)); // true
System.out.println(s1.equals(s3)); // false
// System.out.println(s3.equals(s1)); // NullPointerException!

1.2 详细说明

1.2.1 使用==比较有两种情况

比较基础数据类型(Java中基础数据类型包括八中:short,int,long,float,double,char,byte,boolen):

这种情况下,==比较的是他们的值是否相等。

引用间的比较:

在这种情况下,==比较的是他们在内存中的地址,也就是说,除非引用指向的是同一个new出来的对象,此时他们使用 ==去比较得到true,否则,得到false。

1.2.2 使用equals进行比较

equals追根溯源,是Object类中的一个方法,在该类中,equals的实现也仅仅只是比较两个对象的内存地址是否相等,但在一些子类中,如:String、Integer 等,该方法将被重写。

1.2.3 以 String类为例子说明 eqauls==的区别:

在开始这个例子之前,同学们需要知道JVM处理String的一些特性。

Java的虚拟机在内存中开辟出一块单独的区域,用来存储字符串对象,这块内存区域被称为字符串缓冲池。

当使用 String a = "abc"这样的语句进行定义一个引用的时候,首先会在字符串缓冲池中查找是否已经相同的对象,如果存在,那么就直接将这个对象的引用返回给a,如果不存在,则需要新建一个值为"abc"的对象,再将新的引用返回a。

String a = new String("abc");这样的语句明确告诉JVM想要产生一个新的String对象,并且值为"abc",于是就 在堆内存中的某一个小角落开辟了一个新的String对象 。

即使多次调用 new String("abc");

  • ==在比较引用的情况下,会去比较两个引用的内存地址是否相等。
    String str1 = "abc"; // true
String str2 = "abc";

System.out.println(str1 == str2); // true 因为在str2赋值之前,str1的赋值操作就已经在内存中创建了一个值为"abc"的对象了,然后str2将会与str1指向相同的地址。
System.out.println(str1.equals(str2)); // true

String str2 = new String("abc");
System.out.println(str1 == str2); // false
System.out.println(str1.equals(str2)); // true

以上代码将会输出

false true第一个true: **第二个true:**因为 String已经重写了 equals方法:为了方便大家阅读我贴出来,并且在注释用进行分析: public boolean equals(Object anObject) {

//如果比较的对象与自身内存地址相等的话 //就说明他两指向的是同一个对象 //所以此时equals的返回值跟==的结果是一样的。 if (this == anObject) { return true; } //当比较的对象与自身的内存地址不相等,并且 //比较的对象是String类型的时候 //将会执行这个分支 if (anObject instanceof String) { String anotherString = (String)anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; //在这里循环遍历两个String中的char while (n-- != 0) { //只要有一个不相等,那么就会返回false if (v1[i] != v2[i]) return false; i++; } return true; } } return false; } 进行以上分析之后,就不难理解第一段代码中的实例程序输出了。

Loading Comments...