【Java基础之Object类(一)】Java中Object类中的所有方法(toString、equals、hashCode、clone、finalize、wait和notify等)详解

一、Object中所有方法简介:

在根类Object中包含一下方法: 

  1. clone();
  2. equals();
  3. finalize();
  4. getClass();[align=left][/align]
  5. notify(),notifyAll();
  6. hashCode();
  7. toString();
  8. wait();
我们知道所有的类都是继承于Object,所以我们编写的类默认都具有这些方法,究竟这些方法做什么用,需要让所有的对象都拥有,我将一一来解释。 
     首先大家要明白回调(callback)方法,所谓回调方法就是程序在运行特定功能时JVM会自动调动这些方法,假设你使用System.out.print(obj)打印出对象obj信息,则运行时JVM会自动调用obj对象的toString()方法,toString()方法就是回调方法。理解回调方法后,下面我们来看这些方法: 

  • clone():clone方法主要用于克隆当前对象,制作本地对象,这肯定需要在所有对象中所拥有,在讲解参数按值传递和按引用传递时再讲解它的用法;但clone()在Object中protected方法,所以子类实现需要覆盖此方法并实现Cloneable接口,那样才能在外部实现clone功能equals()、toString()和hashCode():这两个方法主要用于比较两个对象是否相等,查看Object源代码(要多查看源代码便于自己理解)知道,默认的equals()是:
    Java代码   收藏代码
    1. boolean equals(Object obj){  
    2.                               return this == obj;  
    3.                           }  

    ==只有当两个对象地址相同时才返回true,所以默认的equals()方法根本没什么用,因为对象在内存中的地址(基本类型不同)肯定不同的;所以我们编写类时最好覆盖默认的equals()、hashCode()和toString()方法(查看JDK中的类也大部分覆盖了这些方法),

    hashCode():默认的hashCode()返回的值就是对象在内存中的地址。

    toString():而默认的toString()方法就是打印出对象的地址。

    toString()和equals()方法内部是通过hashCode()的返回值来实现的,hashCode()是本地(native)方法,所谓本地方法就是使用其他语言(C或C++)编写的,我们可以通过本地接口(JNI)编写本地方法;

  • finalize():这是GC清理对象之前所调用的清理方法,是回调方法,我们可以覆盖这个方法写一些清理的代码,GC会自动扫描没有引用的对象,即对象赋值为null;可以通过调用System.runFinalization()或System.runFinalizersOnExit()强制GC清理该对象前调用finalize()方法,GC有时不会调用对象的finalize()方法(由JVM决定);
  • getClass():返回当前对象的Class类的对象引用,用于取得类名等(方法查看API);
  • notify()、notifyAll()和wait():这三个方法主要用于多线程中。 

    • wait():执行了该方法的线程释放对象的锁,JVM会把该线程放到对象的等待池中。该线程等待其它线程唤醒
    • notify():执行该方法的线程唤醒在对象的等待池中等待的一个线程,JVM从对象的等待池中随机选择一个线程,把它转到对象的锁池中。

    通常可以使用synchronized和notify,notifyAll以及wait方法来实现线程之间的数据传递及控制。对于对象obj来说:

    • obj.wait():该方法的调用,使得调用该方法的执行线程(T1)放弃obj的对象锁并阻塞,直到别的线程调用了obj的notifyAll方法、或者别的线程调用了obj的notify方法且JVM选择唤醒(T1),被唤醒的线程(T1)依旧阻塞在wait方法中,与其它的线程一起争夺obj的对象锁,直到它再次获得了obj的对象锁之后,才能从wait方法中返回。(除了notify方法,wait还有带有时间参数的版本,在等待了超过所设时间之后,T1线程一样会被唤醒,进入到争夺obj对象锁的行列;另外中断可以直接跳出wait方法)
    • obj.notify():该方法的调用,会从所有正在等待obj对象锁的线程中,唤醒其中的一个(选择算法依赖于不同实现),被唤醒的线程此时加入到了obj对象锁的争夺之中,然而该notify方法的执行线程此时并未释放obj的对象锁,而是离开synchronized代码块时释放。因此在notify方法之后,synchronized代码块结束之前,所有其他被唤醒的,等待obj对象锁的线程依旧被阻塞。
    • obj.notifyAll():与notify的区别是,该方法会唤醒所有正在等待obj对象锁的线程。(不过同一时刻,也只有一个线程可以拥有obj的对象锁)
    注:方法调用一定要处于synchronized关键字包含的代码中,即锁控制的区域。

    举例:
    int nsize=5;
    synchronized(obj){
         if(nsize>=5){
            nsize--;
            obj.wait(); //该句执行后,当前线程阻塞,后面代码不会执行
         }
         nsize++;
         obj.notify(); //释放当前对象锁
    }
    上述代码使得nszie始终会小于等于5,超过5时自动阻塞。

    二、几种常用方法详解

    1. equals方法
    Object类中的equals方法用于检测一个对象是否等于另一个对象,具体是比较两个对象是否具有相同的引用。这一点与“==”具有相同的功效。即是说,对于除开String对象的其他对象,equals与 == 具有一样的效果。而java.lang.String重写了equals方法,下面对这一点细说。

    Object类中:
     public boolean equals(Object obj) {
       return (this == obj);
     }
    可以看出,equals判断实际上进行的就是 == 判读。
    而在String中:
     public boolean equals(Object anObject) {
    if (this == anObject) {
     return true;
     }
    if (anObject instanceof String) {
    String anotherString = (String)anObject;
     int n = count;
     if (n == anotherString.count) {
     char v1[] = value;
     char v2[] = anotherString.value;
     int i = offset;
     int j = anotherString.offset;
     while (n-- != 0) {
    if (v1[i++] != v2[j++])
     return false;
     }
     return true;
     }
     }
     return false;
     }
    先是判断两个对象是否是否有一样的引用,再判断两个String对象是否有相同的长度,接着比较每一个位置上的字符是否相同。
    2. hasCode方法
    散列码(hash code)是由对象导出的一个整型值。散列码是没有规律的,如果x和y是两个不同的对象,那x.hashCode()与y.hashCode()一般是不相同的。
    String类使用以下算法计算散列码:
     public int hashCode() {
     int h = hash;
     if (h == 0) {
     int off = offset;
     char val[] = value;
     int len = count;
    
     for (int i = 0; i < len; i++) {
     h = 31*h + val[off++];
     }
     hash = h;
     }
     return h;
     }

    即是说,String类的散列码是由内容导出的。如果两个String对象的内容相同,它们的散列码也相同。

    而Object中,每个对象都有一个默认的散列码,其值为对象的存储地址。
    equals若返回的是true,则对象的散列码必须一致。
    3. toString方法
    Object类定义了toString方法,打印输出对象所属的类名和散列码。
     public String toString() {
     return getClass().getName() + "@" + Integer.toHexString(hashCode());
     }
    只要一个对象与一个字符串通过操作符“+”连接起来,Java编译就会自动的调用toString方法,以便获得这个对象的字符串描述。
     Point p = new Point ( 10, 20 ) ;
     String message = "The current position is " + p ; //调用p.toStr

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值