Object hashcode equals

Object

the parent class for all the class.

public class Object {
	//注册本地方法
    private static native void registerNatives();
    static {
        registerNatives();
    }
    //获取运行时对象的类
	public final native Class<?> getClass();
	//获取对象的hash值
	public native int hashCode();
	//判断对象是否相等
	public boolean equals(Object obj) {
        return (this == obj);
    }
    //创建并返回该对象的一个拷贝
    protected native Object clone() throws CloneNotSupportedException;
    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
    //唤醒在此对象监视器上处于等待状态的单个线程,选择是任意的
    public final native void notify();
    //唤醒所有在此对象监视器上的线程
    public final native void notifyAll();
    //当前线程调用对象的wait方法,当前线程释放对象锁,进入等待队列,依靠其他线程唤醒,或等待时间到后自动唤醒
    public final native void wait(long timeout) throws InterruptedException;
    public final void wait(long timeout, int nanos) throws InterruptedException {
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos > 0) {
            timeout++;
        }

        wait(timeout);
    }
    //当前线程调用对象的wait方法,当前线程释放对象锁,进入等待队列,依靠其他线程唤醒
    public final void wait() throws InterruptedException {
        wait(0);
    }
    protected void finalize() throws Throwable { }
}

getclass()

获取运行时对象的类

hashcode()

在这里插入图片描述

Hash(散列),将任意长度的输入,通过hash算法(常见Hash算法)变换成固定长度的输出,输出值就是hashcode(散列值,哈希值)。关于hashcode的一些注意事项:

  1. 如果散列表中存在和散列原始输入K相等的记录,那么K必定在f(K)的存储位置上
  2. 不同输入经过hash算法可能得到同一个hashcode,这种现象被称为hash碰撞
  3. 如果两个hash值不同(前提是同一Hash算法),那么这两个Hash值对应的原始输入必定不同

HashCode作用:JVM每new一个Object,它都会将这个Object丢到一个Hash表中去,这样的话,下次做Object的比较或者取这个对象的时候(读取过程),它会根据对象的HashCode再从Hash表中取这个对象。这样做的目的是提高取对象的效率Hashcode确定对象的存储位置,便于快速查找

equals()

equals()是用于比较两个对象的是否相等的

  1. 比较类型相同
  2. 比较成员变量的值相等

一般推荐如果类重写了equals()方法,那么hashcode()也要重写 具体原因如下

public class MyHash {
    public static void main(String[] args) {
        MyBusiness m1 = new MyBusiness();
        MyBusiness m2 = new MyBusiness();
        MyBusiness m3 = new MyBusiness();
        
        Set testSet =new HashSet<MyBusiness>();
        testSet.add(m1);
        testSet.add(m2);
        testSet.add(m3);
        System.out.println(testSet.size()); // return 3
    }
}


class MyBusiness{
    private String nameString;
    private int age;

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        MyBusiness other = (MyBusiness) obj;
        if (age != other.age)
            return false;
        if (nameString == null) {
            if (other.nameString != null)
                return false;
        } else if (!nameString.equals(other.nameString))
            return false;
        return true;
    }
}

我们重写了Mybusiness类的equals方法,此时m1,m2,m3三个对象的类型一致,并且成员变量的值一致,因此m1 equals m2 equals m3,我们将三个对象放入set集合中(Set中不会出现重复的数据),但是我们通过打印Set的size方法吗,却发现返回值是3,因此说明Set集合认为那三个对象是不同的。 原因是HashSet使用了Object的hashcode方法,因为hashcode()返回的是对象存储地址经过特定算法返回的值,因此m1,m2,m3的hashcode都不相同,(hashcode不同,则对象一定不同,hashcode相同,对象可能相同可能不同),所以HashSet的size为3.

public class MyHash {
    public static void main(String[] args) {
        MyBusiness m1 = new MyBusiness();
        MyBusiness m2 = new MyBusiness();
        MyBusiness m3 = new MyBusiness();
        
        Set testSet =new HashSet<MyBusiness>();
        testSet.add(m1);
        testSet.add(m2);
        testSet.add(m3);
        System.out.println(testSet.size());  //return 1
    }
}


class MyBusiness{
    private String nameString;
    private int age;

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((nameString == null) ? 0 : nameString.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        MyBusiness other = (MyBusiness) obj;
        if (age != other.age)
            return false;
        if (nameString == null) {
            if (other.nameString != null)
                return false;
        } else if (!nameString.equals(other.nameString))
            return false;
        return true;
    }
}

然后我们同时重写了equals和hashcode方法,此时Hashset和size()返回值是1,此时m1,m2,m3三个对象的hashcode值一致,被划分到同一块区域存储(此时依旧不能保证三个对象相等),然后HashSet会调用m1,m2,m3对象的equals方法,判断出三个对象相等,因此相等的对象不会被存储,HashSet的size只为1

clone()

创建并返回该对象的一个拷贝

wait()/wait(long)

当前线程调用对象的wait()方法,当前线程释放对象锁,进入等待队列,依靠其他线程唤醒(notify()或notifyAll())或者wait(long)等待时间到自动唤醒。

nofity()/notifyAll()

notify()唤醒在此对象监视器上处于等待状态的单个线程,选择是任意的。notifyAll()唤醒在此对象监视器上所有处于等待状态的线程。

//wait() 和notify()实现线程交替执行
public class TicketTest {

    public static void main(String[] args) {
        Ticket ticket =Ticket.getInstance();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                ticket.sellTicket();
            }
        }).start();
        
        ticket.sellTicket();
    }
}


class Ticket{
    private static Ticket ticket;
    private int total = 100;
    private Lock reentrantLock = new ReentrantLock();
    private String last;
    
    public static Ticket getInstance() {
        if(ticket == null) {
            ticket=new Ticket();
        }
        return ticket;
    }
    
    public synchronized void sellTicket() {
        String threadName = Thread.currentThread().getName();
        while(true) {
            try {
                //两次线程的名字一致,是同一线程,则线程释放同步锁,等待其他线程执行后将其唤醒
                if(threadName.equals(last)) {
                    //当前线程进入等待状态,并且释放对象锁
                    this.wait();
                }
                
                if(this.total>0) {
                    this.total--;
                    System.out.println(threadName + " sold one ticket, tickets remain: " + total);
                }else {
                    System.out.println("tickets sold out");
                    System.exit(0);
                }
                
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                last = threadName;
                //线程执行结束后,唤醒此对象监视器上处于等待状态的单个线程
                this.notify();
            }
        }
    }
}

finalize()

用于实例对象被垃圾回收器回收的时触发的操作,当 GC (垃圾回收器) 确定不存在对该对象的有更多引用时,对象的垃圾回收器就会调用这个方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Object类的equals方法是Java中的一个重要方法,用于判断两个对象是否相等。它的默认实现是比较两个对象的引用是否相同,即比较两个对象的内存地址是否相同。但是,我们可以根据需要在自定义类中重写equals方法来定义自己的相等条件。 一般来说,我们在重写equals方法时需要满足以下几个要求: 1. 自反性:对于任何非空引用值x,x.equals(x)应该返回true。 2. 对称性:对于任何非空引用值x和y,如果x.equals(y)返回true,则y.equals(x)也应该返回true。 3. 传递性:对于任何非空引用值x、y和z,如果x.equals(y)返回true,并且y.equals(z)也返回true,则x.equals(z)也应该返回true。 4. 一致性:对于任何非空引用值x和y,多次调用x.equals(y)应该始终返回相同的结果,前提是对象上的信息没有被修改。 5. 非空性:对于任何非空引用值x,x.equals(null)应该返回false。 在实际使用中,我们可以根据对象的属性来判断它们是否相等,比如比较两个字符串的内容是否相同,或者比较两个自定义类对象的特定属性是否相等。在重写equals方法时,通常还需要重写hashCode方法,以确保相等的对象具有相同的哈希码。 需要注意的是,equals方法在比较对象时应该使用instanceof关键字进行类型检查,以避免ClassCastException异常的发生。此外,还可以使用Objects类的equals方法来简化equals方法的实现。 这就是关于Object类的equals方法的一些基本介绍。如果你有任何进一步的问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值