处理对象

==和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方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值