Java基础 Object通用方法

本文介绍了Java中Object类的四个重要方法:equals()用于对象内容比较,需要与hashCode()一起重写以满足散列表需求;hashCode()返回对象的哈希码,影响散列表索引;toString()默认返回对象信息,常需重写以定制输出;clone()用于对象复制,分为浅拷贝和深拷贝,实现时需注意接口与权限问题。

目录

equals()方法

hashCode()方法

toString()方法

clone()方法 



equals()方法

        当需要比较对象是否相等时,往往需要采取重写equals方法和hashcode方法。

        用来比较两个引用的虚地址。当且仅当两个引用在物理上是同一个对象时,返回值为true,否则将返回false

原型:

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

一般会用来比较两个对象的内容是否相等,因此要重写equals方法,如果不重写的话,比较的内存地址,new出来的两个对象,内存地址是不一样的。

@Override
    public boolean equals(Object obj) {
        //如果是同一个对象返回true,反之返回false
        if (this == obj){
            return true;
        }
        if (obj == null){
            return false;
        }
        //判断类型是否相同
        if (this.getClass() != obj.getClass()){
            return false;
        }
        Student student = (Student) obj;
        return age == student.age &&
                Objects.equals(name, student.name);
    }

java对于equals()的要求

自反性

public class Test01 {
    public static void main(String[] args) {
        Student st1 = new Student();
        Student st2 = new Student();
        System.out.println(st1.equals(st1));//true
    }
}

对称性

public class Test01 {
    public static void main(String[] args) {
        Student st1 = new Student();
        Student st2 = new Student();
        System.out.println(st1.equals(st2) == st2.equals(st1));//true
    }
}

类推性

public class Test01 {
    public static void main(String[] args) {
        Student st1 = new Student("张三",18);
        Student st2 = new Student("张三",18);
        Student st3 = new Student("张三",18);
        System.out.println(st1.equals(st2));
        System.out.println(st2.equals(st3));
        if (st1.equals(st2) && st2.equals(st3)){
            System.out.println(st1.equals(st3));//true
        }
    }
}

一致性

stu1.equals(stu2) == stu1.equals(stu2);

非空性

stu1.equals(null);//false

 

equals()与 ==

  • 对于基本类型,== 判断两个值是否相等,基本类型没有 equals() 方法。
  • 对于引用类型,== 判断两个变量是否引用同一个对象,而 equals() 判断引用的对象是否等价。
public class Test01 {
    public static void main(String[] args) {

        Integer x = new Integer(1);
        Integer y = new Integer(1);
        System.out.println(x.equals(y));//true
        System.out.println(x==y);//false
    }
}

hashCode()方法

hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。

在覆盖 equals() 方法时应当总是覆盖 hashCode() 方法。

hashCode() 定义在JDK的Object.java中,这就意味着Java中的任何类都包含有hashCode() 函数。

hashCode() 在散列表中才有用,在其它情况下没用在散列表中hashCode() 的作用是获取对象的散列码,进而确定该对象在散列表中的位置。

在散列表中,
       1、如果两个对象相等,那么它们的hashCode()值一定要相同;
       2、如果两个对象hashCode()相等,它们并不一定相等。

toString()方法

默认返回 ToStringExample@4554617c 这种形式,其中 @ 后面的数值为散列码的无符号十六进制表示。

public class ToStringExample {
    private int number;

    public ToStringExample(int number) {
        this.number = number;
    }
}
public class ToStringExampleTest {
    public static void main(String[] args) {
        ToStringExample ts = new ToStringExample(100);
        System.out.println(ts.toString());

    }
}

注意:

toString()方法与类使用要重写该方法,可自定义输出内容

@Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

toString()方法与数据组使用时,调用Arrays中的toString方法

toString()方法还可以用于对象数组,使用时既要在类中重写toString()方法又要调用Arrays类的toString()方法。

clone()方法 

clone() 是 Object 的 protected 方法,它不是 public,一个类不显式去重写 clone(),其它类就不能直接去调用该类实例的 clone() 方法。

源码如下:

/*
Creates and returns a copy of this object. The precise meaning of "copy" may depend on the class of the object.
The general intent is that, for any object x, the expression:
1) x.clone() != x will be true
2) x.clone().getClass() == x.getClass() will be true, but these are not absolute requirements.
3) x.clone().equals(x) will be true, this is not an absolute requirement.
*/
protected native Object clone() throws CloneNotSupportedException;

其中有一个 native 方法,众所周知 native方法是非java语言实现的方法,仅供程序调用。

1) x.clone() != x will be true
2) x.clone().getClass() == x.getClass() will be true, but these are not absolute requirements.
3) x.clone().equals(x) will be true, this is not an absolute requirement.

  1. 第一次声明保证克隆对象将有单独的内存地址分配。
  2. 第二次声明表明,原始和克隆的对象应该具有相同的类类型,但它不是强制性的。
  3. 第三声明表明,原始和克隆的对象应该是平等的equals()方法使用,但它不是强制性的

因为每个类直接或间接的父类都是Object,因此它们都含有clone()方法,但是因为该方法是protected,所以都不能在类外进行访问。

要想对一个对象进行复制,就需要对clone方法覆盖。
 

为什么要进行克隆?

克隆的对象可能包含一些已经修改过得属性,当需要一个型的对象来保存当前“状态“时就得使用clone方法。且clone是一个native方法,运行快。

常见的Object a=new Object();Object b;b=a;这种形式的代码复制的是引用,即对象在内存中的地址,a和b对象仍然指向了同一个对象。

而通过clone方法赋值的对象跟原来的对象同是时独立存在的。

克隆的实现:

浅拷贝(ShallowClone)

一般步骤:

1、被复制的类需要实现Cloneabe接口,该接口为标记接口,不含任何方法。如果不实现的话,调用clone会抛异常(CloneNotSupportedException)

2、覆盖clone方法,访问修饰符改为public,方法中调用super.clone()方法得到需要的复制对象

拷贝对象和原始对象的引用类型引用同一个对象。

在浅克隆中,如果原型对象的成员变量是值类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。

通过覆盖Object类的clone()方法可以实现浅克隆。

public class Student implements Cloneable {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public Object clone() {
        Student stu = null;
        try {
            stu = (Student)super.clone();
        }catch (CloneNotSupportedException e){
            e.printStackTrace();
        }
        return stu;
    }
}
public class CloneTest {
    public static void main(String[] args) {
        Student student = new Student();
        student.setName("小明");

        Student stu = (Student)student.clone();
        System.out.println(student.getName());//小明
        System.out.println(stu.getName());//小明

        student.setName("大明");
        System.out.println(student.getName());//大明
        System.out.println(stu.getName());//小明
    }
}

深拷贝(DeepClone)

拷贝对象和原始对象的引用类型引用不同对象。

在深克隆中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。

实现深克隆,可以通过覆盖Object类的clone()方法实现,也可以通过序列化(Serialization)等方式来实现

public class Address implements Cloneable {
    private String address;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public Object clone() {
        Address add = null;
        try {
            add = (Address)super.clone();
        }catch (CloneNotSupportedException e){
            e.printStackTrace();
        }
        return add;
    }
}
public class Student implements Cloneable {
    private String name;

    private Address addr;

    public Address getAddr() {
        return addr;
    }

    public void setAddr(Address addr) {
        this.addr = addr;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public Object clone() {
        Student stu = null;
        try {
            stu = (Student)super.clone();//浅复制
        }catch (CloneNotSupportedException e){
            e.printStackTrace();
        }
        stu.addr = (Address)addr.clone();//深度复制
        return stu;
    }
}
public class CloneTest {
    public static void main(String[] args) {
        Address addr = new Address();
        addr.setAddress("北京市");
        Student student = new Student();
        student.setName("小明");
        student.setAddr(addr);

        Student stu = (Student)student.clone();
        System.out.println(student.getName()+ student.getAddr().getAddress());//小明
        System.out.println(stu.getName()+stu.getAddr().getAddress());//小明

        addr.setAddress("河北省");
        System.out.println(student.getName() +student.getAddr().getAddress());//大明
        System.out.println(stu.getName()+stu.getAddr().getAddress());//小明

    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清沐知秋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值