==和equals
之前我们比较基本数据类型的方式很简单,1==1,true == true ,2 == 3,通过“==”的方式比较两个数据是否相等。
但是之前,我们使用包装类包装了两个数据,比较这两个包装类的时候,我们发现,即便包装的数据一样,但是使用“==”返回false。
class EqualsTest
{
publicstatic void main(String[] args){
Personp1 = new Person("小明","帝都",28);
Personp2 = new Person("大明","魔都",22);
System.out.println(p1== p2);//false
Personp3 = new Person("大明","魔都",22);
System.out.println(p3== p2);//false
Integerinteger1 = new Integer(1);
Integerinteger2 = new Integer(1);
System.out.println(integer2== integer1);//false
}
}
class Person
{
publicPerson(String name ,String address ,int age){
this.name= name;
this.address= address;
this.age= age;
}
Stringname ;
Stringaddress;
int age;
}
我们在比较基本数据类型时,可以直接使用==来判断是否相等。
但是,引用数据类型,不可以使用==来判断,即便,两个引用类型指向的对象属性完全一致,但是依然返回false。
这是因为:对象使用“==”比较的话,比较的是引用所指向对象的地址值,比较是对象是否同一个。如下案例,当两个引用变量指向同一个对象,再比较的话,就是true,因为两个变量的引用都是指向同一个对象,所以比较的地址值也一样,所以返回true。否则,返回false.
class EqualsTest
{
publicstatic void main(String[] args){
Personp1 = new Person("小明","帝都",28);
Personp2 = p1;
System.out.println(p1== p2);//true
}
}
class Person
{
publicPerson(String name ,String address ,int age){
this.name= name;
this.address= address;
this.age= age;
}
Stringname ;
Stringaddress;
int age;
}
但是,在开发中,我们经常会遇到一种问题,就是我们需要把属性相同的两个对象认为是同一个对象。这个时候,我们使用equals方法来解决这种问题。
比较两个对象,Object类提供了equals方法供我们自定义比较两个对象是否相等。在定义类的时候,我们可以重写该方法,来达到自定义判断两个对象是否相等的目的。当对象调用equals方法的时候,就会执行该对象重写的equals方法来判断与传入的对象是否是同一个对象,这样就达到了手动控制的目的。
但是,如果没有重写equals方法,那么就是执行默认的object提供的equals方法。
我们翻开原码发现,默认的提供的equals方法,其实就是使用==来比较两个对象,比较的是指向的对象的地址值。当我们没有重写equals方法,执行该方法实际就是执行了==运算,比较两个对象的地址值是否同一个。
一般来说,java提供的很多类都重写了equals方法,用来判断。
练习:
class EqualsTest
{
public static void main(String[] args){
Person p1 = new Person("小明","帝都",28);
Person p2 = new Person("大明","魔都",22);
System.out.println(p1.equals(p2));//false
Person p3 = new Person("大明","魔都",22);
System.out.println(p3.equals(p2));//true
}
}
class Person
{
public Person(String name ,String address ,int age){
this.name= name;
this.address= address;
this.age= age;
}
public boolean equals(Object obj) {
//判断地址是否一样
if(this== obj){
retur ntrue;
}
//判断传入的对象引用是否为null
if(obj== null){
return false;
}
//判断传入的对象是否该属于本类类型对象
if(!(obj instanceof Person)){
return false;
}
//将传入对象强转
Person ap = (Person)obj;
//依次判断传入对象的属性与本对象属性是否一致
//判断name
if(this.name== null){
if(ap.name!=null){
return false;
}
}else{
if(!this.name.equals(ap.name)){
return false;
}
}
//判断age
if(this.age!= ap.age){
return false;
}
//判断address
if(this.address== null){
if(ap.address!=null){
return false;
}
}else{
if(!this.name.equals(ap.name)){
return false;
}
}
//到这一步,说明所有属性都相同
return true;
}
String name ;
String address;
int age;
}
toString方法:(自定义打印对象内容)
有的时候,我们需要知道一下对象的内容,那么我们将对象打印输出查看,但是我们直接输出的话,打印结果如下:
我们发现,这个结果并不是我们需要的。假设我们需要打印对象,打印对象的内容如属性,那么这个时候,我们需要自定义一下打印的内容。
Object类提供了默认方法toString方法,该方法返回该对象的字符串表示形式。他默认打印的是对象的类型+@+哈希值。当我们需要自定义对象的字符串表现形式时,我们可以重写toString方法。
如下:object类中源码默认打印:
public String toString() {
return getClass().getName() + "@" +Integer.toHexString(hashCode());
}
我们发现,直接打印对象,就会默认调用该对象的toString方法,打印该方法的返回值。
class EqualsTest
{
public static void main(String[] args){
Person p1 = new Person("小明","帝都",28);
//直接打印对象,就是打印对象toString方法返回值
System.out.println(p1);
Person p2 = new Person("大明","帝都",22);
System.out.println(p2.toString());
}
}
class Person
{
public Person(String name ,String address ,int age){
this.name= name;
this.address= address;
this.age= age;
}
public String toString(){
Stringresult = "name:" + name +";address:" + address+";age:" + age;
return result;
}
public boolean equals(Object obj) {
//判断地址是否一样
if(this== obj){
return true;
}
//判断传入的对象引用是否为null
if(obj== null){
return false;
}
//判断传入的对象是否该属于本类类型对象
if(!(obj instanceof Person)){
return false;
}
//将传入对象强转
Person ap = (Person)obj;
//依次判断传入对象的属性与本对象属性是否一致
//判断name
if(this.name== null){
if(ap.name!=null){
return false;
}
}else{
if(!this.name.equals(ap.name)){
return false;
}
}
//判断age
if(this.age!= ap.age){
return false;
}
//判断address
if(this.address== null){
if(ap.address!=null){
return false;
}
}else{
if(!this.name.equals(ap.name)){
return false;
}
}
//到这一步,说明所有属性都相同
return true;
}
String name ;
String address;
int age;
}
哈希值:
在之前,我们翻开Object的源码发现,会打印类名+@+哈希值。
那么哈希值到底是什么东西?
每个对象,都会有一个唯一的哈希值,当使用“==”比较两个对象,其实比较的就是哈希值!
哈希值是当创建对象后,由虚拟机自动生成,无法更改。
当然,每个对象也提供了获取哈希值的方法hashCode方法,默认返回的就是哈希值。
该方法是Object提供的,可以重写该方法。
什么时候需要用到重写该方法?
在之后课程集合中,判断一些对象是否重复,用到哈希值,重写hashCode方法。