Java中“==”和 equals的区别

“==”的做用:

判断两个变量栈内存中存储的值是否相等,若是相等返回true,若是不相等返回false。数组

有两种形式的比较须要用到比较运算符“==”,一是两个基本数据类型之间的比较,二是两个引用数据类型之间的比较。缓存

1.两个基本数据类型之间的比较:
性能

  八大基本数据类型:byte,short,int,long,double,folat,boolean,char,其中占一个字节的是byte和boolean,short和char占两个字节,int,float占四个字节,double和long占8个字节,这八种数据变量中直接存储其值,变量是在栈中存储的。this

  所以:“==”比较基本数据类型时,比较的是值。spa

  JAVA 基本数据类型建立单个变量是不能够new的,由于new的都是对象。但建立基本数据类型数组时能够new,由于数组是对象。code

int a = 5; int b = 5; int c = 6; System.out.println(a == b);  // 5 == 5 System.out.println(a == c);  // 5 == 6

  建立了是三个基本数据类型的变量,他们在栈中存储的值就是其数值自己,栈中值由低到高依次为a(5)、b(5)、c(6)。所以“a==b”其本质就是“5==5”,返回true;“a==c”其本质就是“5==6”,返回false。对象

  所以,运行结果依次为:true  false。blog

2.两个引用数据类型之间的比较:
继承

  引用数据类型都是对象,通常都是在堆中被建立,变量中存储的是堆中对象的地址引用。内存

  所以,“==”比较引用类型时,比较的是地址。

  • 通常的类用new来建立对象,是在堆中开辟空间来存储的,每一个对象都有惟一的地址;
  • 数据类型的包装类既能够用new来建立,在堆中开辟空间存储,也能够直接建立,经过自动装箱的机制来完成对象在堆中的建立。

  这里要注意两个数据类型,一个是String类型,一个是Integer类型。具体请看案例分析:

String str1 = new String("abc");    // 0x123 String str2 = new String("abc");    // 0x262 String str3 = new String("xyz");    // 0x762
System.out.println(str1
== str2);  // 0x123 == 0x262 System.out.println(str1 == str3);  // 0x123 == 0x762

  用new建立了三个String类型的对象,建立的三个对象都在堆中,所以有不一样的地址引用。三个变量在栈中存储的是三个对象的地址引用,其值各不相同。

  所以,运行结果依次为:false false。

String str1 = "abc";    // 0x111   String str2 = "abc";    // 0x111 String str3 = "xyz";    // 0x123 System.out.println(str1 == str2);  // 0x111 == 0x111 System.out.println(str1 == str3);  // 0x111 == 0x123

   直接建立了三个String类型的对象,建立的字符串在字符串常量池中,所以建立已经存在的字符串会直接返回其地址引用。str2在栈中存储的值和str1在栈中存储的值是同样的,都是字符串“abc”在字符串常量池中的地址引用,而str3在栈中存储的是字符串“xyz”在字符串常量池中的地址引用。

  所以,运行结果一次为:true  false。

Integer s1 = new Integer(100); Integer s2 = new Integer(100); Integer s3 = new Integer(200); System.out.println(s1 == s2); System.out.println(s1 == s3);

  用new建立了三个Integer类型的对象,建立的三个对象都在中,所以有不一样的地址引用。三个变量在栈中存储的是三个对象的地址引用,其值各不相同。

  所以,运行结果依次为:false false。

Integer n1 = 100; Integer n2 = 100; System.out.println(n1 == n2); Integer a1 = new Integer(100); Integer a2 = new Integer(100); System.out.println(a1 == a2); Integer m1 = 300; Integer m2 = 300; System.out.println(m1 == m2); Integer b1 = new Integer(300); Integer b2 = new Integer(300); System.out.println(b1 == b2);

  运行结果依次为:true  false  false false。为何是这样呢?

  两个new的好解释,由于是在堆中建立的,每一个对象有惟一的地址,所以会返回false。但第一个和第三个是啥状况呢?

  这是由于在Java中为了提升空间和时间性能,Integer类中有一个静态内部类IntegerCache,在IntegerCache类中有一个Integer数组,用以缓存当数值范围为[-128,127]时的Integer对象。因此在自动装箱的过程当中,若是数值在[-128,127]内,会直接返回其地址引用,如果不在才在堆中建立对象。

equals的做用:

  在Java中许多系统提供的类都定义了equals方法,这个方法用来比较两个独立对象的内容是否相同,而不是比较引用值自己的。自定义方法的定义大体以下(以String类为例):

public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String aString = (String)anObject; if (!COMPACT_STRINGS || this.coder == aString.coder) { return StringLatin1.equals(value, aString.value); } } return false; }

  可是若是一个自定义的类中没有定义equals方法,那么它将继承Object类的equals方法,Object类的equals方法定义以下:

public boolean equals(Object obj) { return (this == obj);
}

  能够看到,若是一个类中没有显式的定义equals方法,那么equals方法的做用和“==”的做用是同样的,都是比较两个变量指向的对象是不是同一对象。

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

  “==”比较的是地址,str1和str2在堆中的地址是不同的,所以结果返回false,由于String类型自定义了equals方法,此equals方法比较的是对象的内容,所以结果返回true。

  因此运行结果依次为false   true。

public class Test { public Test() {} public static void main(String[] args) { Test a = new Test(); Test b = new Test(); Test c = a; System.out.println(a.equals(b)); System.out.println(a.equals(c)); } }

  本身定义的的Test类,并无自定义equals方法,所以euqals方法和“==”的做用是同样的,比较的是对象的地址,也就是说判断两个对象是不是同一个。a和b中存储的地址分别是两个不一样对象的地址,c被赋值了a中存储的地址,也就是说a和c指向的是同一个对象。

  所以,运行结果依次是:false   true。

总结一下:

  运算符“==”只是用来比较两个变量在栈中存放的值是否相同

  equals是类的成员方法通常用来比较两个独立对象的内容是否相同(要看具体的定义)。若是自定义的类中没有定义equals方法,则会继承Object类的equals方法,其做用与“==”相同。

相关文章
相关标签/搜索