Java对象equals、clone

一、==、equals、hashcode

Java中比较对象通常使用==符和equals方法。

== ⽐较的是对象地址,equals 是Object的一个方法,通常子类通过重写它来比较值。

equals是Object类的方法,实现如下:

public boolean equals(Object obj) {
        return (this == obj); 就是调用==
    }

Object类中的方法就是==,但是可以通过重写equals方法进行比较。

String类就通过重写方法来比较值。

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        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;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

HashCode是Java对象的签名,hashcode可以减少equals比较的次数,提高运算效率。

hashCode是Object类的一个native方法,通过哈希函数给每个对象生成一个哈希值,用来方便Java内部查找对象。

但是哈希是会有冲突的,所以哈希值相同,不代表对象就一定相同。

public native int hashCode();

通常重写equals方法就会重写hashCode方法。

集合 Set 和 Map 加⼊元素会在调⽤他们的 put (Set add ⽅法的背后也是 HashMap 的 put)⽅法时, 会先判断 hash 值是否相等。

二、clone

clone是Cloneable接口的方法,继承该接口可以复制Java对象。

Java是值传递,或者说赋值传递。引用类型通过=并没有被复制,只是被新的句柄(或者说字段)引用了,还是一个对象。一个句柄修改对象后,其他句柄也会受到影响。(在 Java 中,A a1 = a2,我们需要理解的是这实际上复制的是引用,也就是说 a1 和 a2 指向的是同一个对象。因此,当 a1 变化的时候,a2 里面的成员变量也会跟着化。)

重写Cloneable接口的clone方法,可以进行对象的浅拷贝和深拷贝。

浅拷贝

创建一个新对象,然后将当前对象的非静态字段复制到该新对象,如果字段是值类型的,那么对该字段执行复制;如果该字段是引用类型的话,则复制引用但不复制引用的对象。
因此,原始对象及其副本引用同一个对象。

import java.util.LinkedList;

/**
 * @author cgl
 * @version 1.0
 * @desc
 * @date 2021/3/4 9:55
 */
public class ReTry implements Cloneable {

    private int id;//基本类型
    //引用类型
    private LinkedList<Integer> list=new LinkedList<>();

    public ReTry() {
        this.id = 1001;
        this.list.add(10);
    }


    @Override
    protected ReTry clone() throws CloneNotSupportedException {
        ReTry c=(ReTry)super.clone(); //调用clone方法
        
//        c.list= (LinkedList<Integer>) c.list.clone();
        return c;
    }

    @Override
    public String toString() {
        return "ReTry{" +
                "id='" + id + '\'' +
                ", list=" + list +
                '}';
    }

    public static void main(String[] args) throws CloneNotSupportedException {
        ReTry aTry = new ReTry();

        ReTry clone = aTry.clone();


        aTry.id=1002;//修改了基本类型
        aTry.list.add(5);//修改了引用类型

        System.out.println(clone);
        System.out.println(aTry);
        /*
        ReTry{id='1001', list=[10, 5]}
        ReTry{id='1002', list=[10, 5]}
         */

    }
}

原对象修改了int变量后,副本的int变量没有变化。

修改了List,副本的也变化了,因为list还是引用的同一对象。

深拷贝

深拷贝不仅复制对象本身,而且复制对象包含的引用指向的所有对象.

在clone方法中,将引用变量也处理clone.

 c.list= (LinkedList<Integer>) c.list.clone();


此时结果互不影响了。

ReTry{id='1001', list=[10]}
ReTry{id='1002', list=[10, 5]}
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 黑客帝国 设计师:白松林 返回首页