Java基础知识(3)-- Object类

1)equals和==:

   总结来说:

  (1)对于==,如果作用于基本数据类型的变量,则直接比较其存储的“值”是否相等;

        如果作用于引用类型的变量,则比较的是所指向的对象的地址

  (2)对于equals方法,注意:equals方法不能作用于基本数据类型的变量

        如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地

        址;诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对

        象的内容。所以equals比较的内容取决于是否重写。


  2hashCodeequals:

   equals原则:

   自反性 对于任意的引用值x,x.equals(x)一定为true。

   对称性。对于任意的引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)也一定返回true。

   传递性。对于任意的引用值x、y和z,如果x.equals(y)返回true,并且y.equals(z)也返回true,那么x.equals(z)也一定返回true。

   一致性。对于任意的引用值x和y,如果用于equals比较的对象信息没有被修改的话,那么,多次调用x.equals(y)也一定返回true。

   与null的比较。对于任意的非空引用值x,x.equals(null)一定返回false。


equals方法重写:

● 检查是否为同一个对象的引用,如果是直接返回 true;

● 检查是否是同一个类型,如果不是,直接返回 false;

● 将 Object 对象进行转型;

● 判断每个关键域是否相等。

public class EqualExample {

    private int x;

    private int y;

    private int z;

    public EqualExample(intx, int y, int z) {

        this.x = x;

        this.y = y;

        this.z = z;

    }

    @Override

    public boolean equals(Object o) {

        if (this == o)return true;

        if (o == null || getClass() != o.getClass()) return false;

        EqualExample that = (EqualExample) o;

        if (x != that.x)return false;

        if (y != that.y)return false;

        return z == that.z;

    }

}


String类中equals方法实现:

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() 返回散列值,而 equals() 是用来判断两个对象是否等价。等价的两个对象散列值一定相同,但是散列值相同的两个对象不一定等价。

在覆盖 equals() 方法时应当总是覆盖 hashCode() 方法,保证等价的两个对象散列值也相等。

下面的代码中,新建了两个等价的对象,并将它们添加到 HashSet 中。我们希望将这两个对象当成一样的,只在集合中添加一个对象,但是因为 EqualExample 没有实现 hasCode() 方法,因此这两个对象的散列值是不同的,最终导致集合添加了两个等价的对象。

EqualExample e1 = new EqualExample(1, 1, 1);

EqualExample e2 = new EqualExample(1, 1, 1);

System.out.println(e1.equals(e2)); // true

HashSet set = new HashSet<>();

set.add(e1);

set.add(e2);

System.out.println(set.size());  // 2


   hashCode原则:

   第一:在某个运行时期间,只要对象的(字段的)变化不会影响equals方法的决策结果,那么在这个期间,无论调用多少     次hashCode,都必须返回同一个散列码。

   第二:通过equals调用返回true的2个对象的hashCode一定一样。

   第三:通过equasl返回false的2个对象的散列码不需要不同,也就是他们的hashCode方法的返回值允许出现相同的情况。

   总结一句话:等价的(调用equals返回true)对象必须产生相同的散列码。不等价的对象,不要求产生的散列码不相同。

需要在上述EqualExample类中重写hashCode方法,如下所示:

@Override

public int hashCode() {

    int result = 17;

    result = 31 * result +x;

    result = 31 * result +y;

    result = 31 * result +z;

    return result;

}


String类中的hashCode方法实现:

private int hash;  // Default to 0

public int hashCode() {

        int h = hash;

        if (h == 0 && value.length > 0) {

                char val[] = value;

                for (int i = 0; i < value.length; i++) {

                       h = 31 * h + val[i];

                }

                hash = h;

        }

        return h;

}


3)clone深拷贝与浅拷贝

复制对象 or 复制引用

复制引用
复制对象

浅拷贝:对象中的基本类型进行值拷贝,引用类型对引用地址进行拷贝。

深拷贝:对象中的基本类型和引用类型对应的值都进行拷贝。

如果想要深拷贝一个对象, 这个对象必须要实现Cloneable接口,实现clone方法,并且在clone方法内部,把该对象引用的其他对象也要clone一份 , 这就要求这个被引用的对象必须也要实现Cloneable接口并且实现clone方法。

如果实现彻底的深拷贝,需要使用序列化的方法。

static class Body implements Cloneable{

    public Head head;

    public Body() {}

    public Body(Head head) {this.head = head;}

    @Override

    protected Object clone() throws CloneNotSupportedException {

        Body newBody =  (Body) super.clone();

        newBody.head = (Head) head.clone();

        return newBody;

    }

}

static class Head implements Cloneable{

    public  Face face;

    public Head() {}

    public Head(Face face){this.face = face;}

    @Override

    protected Object clone() throws CloneNotSupportedException {

        return super.clone();

    }

}

public static void main(String[] args) throws CloneNotSupportedException {   

        Body body = new Body(new Head());

        Body body1 = (Body) body.clone();    

        System.out.println("body == body1 : " + (body == body1) );

        System.out.println("body.head == body1.head : " +  (body.head == body1.head));     

}

  打印结果为:

  body == body1 : false

  body.head == body1.head :false


4)wait与notify/notifyAll

可参见Java多线程通信部分。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容