`

(转)java.lang.Object类

阅读更多
转自:http://lavasoft.blog.51cto.com/62575/15456/

一、概述:
       Object类是所有Java类的祖先。每个类都使用 Object 作为超类。所有对象(包括数组)都实现这个类的方法。
在不明确给出超类的情况下,Java会自动把Object作为要定义类的超类。
      可以使用类型为Object的变量指向任意类型的对象。
      Object类有一个默认构造方法pubilc Object(),在构造子类实例时,都会先调用这个默认构造方法。
      Object类的变量只能用作各种值的通用持有者。要对他们进行任何专门的操作,都需要知道它们的原始类型并进行类型转换。例如:
      Object obj = new MyObject();
      MyObject x = (MyObject)obj;

 

二、API预览
    Object()
    默认构造方法
    clone()
    创建并返回此对象的一个副本。
    equals(Object obj)
    指示某个其他对象是否与此对象“相等”。
    finalize()
    当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
    getClass()
    返回一个对象的运行时类。
    hashCode()
    返回该对象的哈希码值。
    notify()
    唤醒在此对象监视器上等待的单个线程。
    notifyAll()
    唤醒在此对象监视器上等待的所有线程。
    toString()
    返回该对象的字符串表示。
    wait()
    导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。
    wait(long timeout)
    导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量。
    wait(long timeout, int nanos)
    导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量。

 

三、方法使用说明
1、equals()方法:用于测试某个对象是否同另一个对象相等。它在Object类中的实现是判断两个对象是否指向同一块内存区域。这中测试用处不大,因为即使内容相同的对象,内存区域也是不同的。如果想测试对象是否相等,就需要覆盖此方法,进行更有意义的比较。例如
class Employee{
... //此例子来自《java核心技术》卷一
    public boolean equals(Object otherObj){
        //快速测试是否是同一个对象
        if(this == otherObj) return true;
        //如果显式参数为null,必须返回false
        if(otherObj == null) reutrn false;
        //如果类不匹配,就不可能相等
        if(getClass() != otherObj.getClass()) return false;
       
        //现在已经知道otherObj是个非空的Employee对象
        Employee other = (Employee)otherObj;

        //测试所有的字段是否相等
        return name.equals(other.name)
            && salary == other.salary
            && hireDay.equals(other.hireDay);
    }
}
Java语言规范要求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,多次调用 x.equals(y) 始终返回 true 或始终返回 false,前提是对象上 equals 比较中所用的信息没有被修改。
对于任何非空引用值 x,x.equals(null) 都应返回 false。


从这里看出,上面的例子是Java规范的equals方法的标准实现,推荐用上面例子的写法实现类的equals方法。

 

2、toString():返回该对象的字符串表示。Object类中的toString()方法会打印出类名和对象的内存位置。几乎每个类都会覆盖该方法,以便打印对该对象当前状态的表示。大多数(非全部)toString()方法都遵循如下格式:类名[字段名=值,字段名=值...],当然,子类应该定义自己的toString()方法。例如:

public String toString(){
    reurn "Employee[name=" + name + ",salary=" + salary + ",hireDay=" + hireDay + "]";
}
toString()方法是非常重要的调试工具,很多标准类库中的类都定义了toString()方法,以便程序员获得有用的调试信息。

 

四、来自SUN公司的java.long.Object类的API文档,网上有chm中文版的,很好找。为了查阅方便,我从SUN公司的JavaDoc站点上复制出来了Object类的API文档。

 

java.lang
类 Object
java.lang.Object

--------------------------------------------------------------------------------

public class Object类 Object 是类层次结构的根类。每个类都使用 Object 作为超类。所有对象(包括数组)都实现这个类的方法。



从以下版本开始:
JDK1.0
另请参见:
Class

--------------------------------------------------------------------------------

构造方法摘要
Object()
           
  方法摘要
protected  Object clone()
          创建并返回此对象的一个副本。
boolean equals(Object obj)
          指示某个其他对象是否与此对象“相等”。
protected  void finalize()
          当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
Class<? extends Object> getClass()
          返回一个对象的运行时类。
int hashCode()
          返回该对象的哈希码值。
void notify()
          唤醒在此对象监视器上等待的单个线程。
void notifyAll()
          唤醒在此对象监视器上等待的所有线程。
String toString()
          返回该对象的字符串表示。
void wait()
          导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。
void wait(long timeout)
          导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量。
void wait(long timeout, int nanos)
          导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量。
 

构造方法详细信息


Object
public Object()方法详细信息


getClass
public final Class<? extends Object> getClass()返回一个对象的运行时类。该 Class 对象是由所表示类的 static synchronized 方法锁定的对象。

返回:
表示该对象的运行时类的 java.lang.Class 对象。此结果属于类型 Class<? extends X>,其中 X 表示清除表达式中的静态类型,该表达式调用 getClass。

--------------------------------------------------------------------------------

hashCode
public int hashCode()返回该对象的哈希码值。支持该方法是为哈希表提供一些优点,例如,java.util.Hashtable 提供的哈希表。
hashCode 的常规协定是:

在 Java 应用程序执行期间,在同一对象上多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是对象上 equals 比较中所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。
如果根据 equals(Object) 方法,两个对象是相等的,那么在两个对象中的每个对象上调用 hashCode 方法都必须生成相同的整数结果。
以下情况不是必需的:如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么在两个对象中的任一对象上调用 hashCode 方法必定会生成不同的整数结果。但是,程序员应该知道,为不相等的对象生成不同整数结果可以提高哈希表的性能。
实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。)

这里需要注意一点:在equals和hashcode未重写或者重写关联的信息一致时,当两个对象的equals返回为true时,hashcode的值返回一定相等,但是当两个hashcode返回一致时,此时的equals并不一定返回true。



返回:
此对象的一个哈希码值。
另请参见:
equals(java.lang.Object), Hashtable




--------------------------------------------------------------------------------

equals
public boolean equals(Object obj)指示某个其他对象是否与此对象“相等”,对两个对象的地址值进行的比较(即比较引用是否相同)
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,多次调用 x.equals(y) 始终返回 true 或始终返回 false,前提是对象上 equals 比较中所用的信息没有被修改。
对于任何非空引用值 x,x.equals(null) 都应返回 false。
Object 类的 equals 方法实现对象上差别可能性最大的相等关系;即,对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true(x == y 具有值 true)。

注意:当此方法被重写时,通常有必要重写 hashCode 方法(获取hashcode值的关联值应该和equals关联的值一致),以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。

参数:
obj - 要与之比较的引用对象。
返回:
如果此对象与 obj 参数相同,则返回 true;否则返回 false。
另请参见:
hashCode(), Hashtable

引用

但是我们必需清楚,当String 、Math、还有Integer、Double。。。。等这些封装类在使用equals()方法时,已经覆盖了object类的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;
}
很明显,这是进行的内容比较,而已经不再是地址的比较。依次类推Double、Integer、Math。。。。等等这些类都是重写了equals()方法的,从而进行的是内容的比较。

equals()相等的两个对象,hashcode()一定相等;
equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。换句话说,equals()方法不相等的两个对象,hashcode()有可能相等。(我的理解是由于哈希码在生成的时候产生冲突造成的)。
反过来:hashcode()不等,一定能推出equals()也不等;hashcode()相等,equals()可能相等,也可能不等。解释下第3点的使用范围,我的理解是在object、String等类中都能使用。在object类中,hashcode()方法是本地方法,返回的是对象的地址值,而object类中的equals()方法比较的也是两个对象的地址值,如果equals()相等,说明两个对象地址值也相等,当然hashcode()也就相等了;在String类中,equals()返回的是两个对象内容的比较,当两个对象内容相等时,
Hashcode()方法根据String类的重写(第2点里面已经分析了)代码的分析,也可知道hashcode()返回结果也会相等。以此类推,可以知道Integer、Double等封装类中经过重写的equals()和hashcode()方法也同样适合于这个原则。当然没有经过重写的类,在继承了object类的equals()和hashcode()方法后,也会遵守这个原则。

4.谈到hashcode()和equals()就不能不说到hashset,hashmap,hashtable中的使用,具体是怎样呢,请看如下分析:
Hashset是继承Set接口,Set接口又实现Collection接口,这是层次关系。那么hashset是根据什么原理来存取对象的呢?
在hashset中不允许出现重复对象,元素的位置也是不确定的。在hashset中又是怎样判定元素是否重复的呢?这就是问题的关键所在,经过一下午的查询求证终于获得了一点启示,和大家分享一下,在java的集合中,判断两个对象是否相等的规则是:
1),判断两个对象的hashCode是否相等
      如果不相等,认为两个对象也不相等,完毕
      如果相等,转入2)
(这一点只是为了提高存储效率而要求的,其实理论上没有也可以,但如果没有,实际使用时效率会大大降低,所以我们这里将其做为必需的。后面会重点讲到这个问题。)
2),判断两个对象用equals运算是否相等
      如果不相等,认为两个对象也不相等
      如果相等,认为两个对象相等(equals()是判断两个对象是否相等的关键)
为什么是两条准则,难道用第一条不行吗?不行,因为前面已经说了,hashcode()相等时,equals()方法也可能不等,所以必须用第2条准则进行限制,才能保证加入的为非重复元素。
比如下面的代码:

public static void main(String args[]){
String s1=new String("zhaoxudong");
String s2=new String("zhaoxudong");
System.out.println(s1==s2);//false
System.out.println(s1.equals(s2));//true
System.out.println(s1.hashCode());//s1.hashcode()等于s2.hashcode()
System.out.println(s2.hashCode());
Set hashset=new HashSet();
hashset.add(s1);
hashset.add(s2);
/*实质上在添加s1,s2时,运用上面说到的两点准则,可以知道hashset认为s1和s2是相等的,是在添加重复元素,所以让s2覆盖了s1;*/
Iterator it=hashset.iterator();
            while(it.hasNext())
            {
             System.out.println(it.next());
            }
最后在while循环的时候只打印出了一个”zhaoxudong”。
输出结果为:false
            true
            -967303459
            -967303459
这是因为String类已经重写了equals()方法和hashcode()方法,所以在根据上面的第1.2条原则判定时,hashset认为它们是相等的对象,进行了重复添加。
但是看下面的程序:
import java.util.*;
public class HashSetTest
{
   public static void main(String[] args)
    {
                 HashSet hs=new HashSet();
                 hs.add(new Student(1,"zhangsan"));
                 hs.add(new Student(2,"lisi"));
                 hs.add(new Student(3,"wangwu"));
                 hs.add(new Student(1,"zhangsan"));
 
                 Iterator it=hs.iterator();
                 while(it.hasNext())
                 {
                        System.out.println(it.next());
                 }
     }
}
class Student
   {
     int num;
     String name;
     Student(int num,String name)
                {
                this.num=num;
                 this.name=name;
                 }
              public String toString()
                {
                    return num+":"+name;
                 }
           }     
输出结果为:
                      1:zhangsan
                   1:zhangsan
                   3:wangwu
                   2:lisi
问题出现了,为什么hashset添加了相等的元素呢,这是不是和hashset的原则违背了呢?回答是:没有
因为在根据hashcode()对两次建立的new Student(1,"zhangsan")对象进行比较时,生成的是不同的哈希码值,所以hashset把他当作不同的对象对待了,当然此时的equals()方法返回的值也不等(这个不用解释了吧)。那么为什么会生成不同的哈希码值呢?上面我们在比较s1和s2的时候不是生成了同样的哈希码吗?原因就在于我们自己写的Student类并没有重新自己的hashcode()和equals()方法,所以在比较时,是继承的object类中的hashcode()方法,呵呵,各位还记得object类中的hashcode()方法比较的是什么吧!!
它是一个本地方法,比较的是对象的地址(引用地址),使用new方法创建对象,两次生成的当然是不同的对象了(这个大家都能理解吧。。。),造成的结果就是两个对象的hashcode()返回的值不一样。所以根据第一个准则,hashset会把它们当作不同的对象对待,自然也用不着第二个准则进行判定了。那么怎么解决这个问题呢??
答案是:在Student类中重新hashcode()和equals()方法。
例如:
  class Student
{
int num;
String name;
Student(int num,String name)
{
            this.num=num;
            this.name=name;
}
public int hashCode()
{
            return num*name.hashCode();
}
public boolean equals(Object o)
{
            Student s=(Student)o;
            return num==s.num && name.equals(s.name);
}
public String toString()
{
            return num+":"+name;
}
}
根据重写的方法,即便两次调用了new Student(1,"zhangsan"),我们在获得对象的哈希码时,根据重写的方法hashcode(),获得的哈希码肯定是一样的(这一点应该没有疑问吧)。
当然根据equals()方法我们也可判断是相同的。所以在向hashset集合中添加时把它们当作重复元素看待了。所以运行修改后的程序时,我们会发现运行结果是:
                      1:zhangsan
                   3:wangwu
                   2:lisi
可以看到重复元素的问题已经消除。
关于在hibernate的pojo类中,重新equals()和hashcode()的问题:
1),重点是equals,重写hashCode只是技术要求(为了提高效率)
2),为什么要重写equals呢,因为在java的集合框架中,是通过equals来判断两个对象是否相等的
3),在hibernate中,经常使用set集合来保存相关对象,而set集合是不允许重复的。我们再来谈谈前面提到在向hashset集合中添加元素时,怎样判断对象是否相同的准则,前面说了两条,其实只要重写equals()这一条也可以。
但当hashset中元素比较多时,或者是重写的equals()方法比较复杂时,我们只用equals()方法进行比较判断,效率也会非常低,所以引入了hashcode()这个方法,只是为了提高效率,但是我觉得这是非常有必要的(所以我们在前面以两条准则来进行hashset的元素是否重复的判断)。
比如可以这样写:
public int hashCode(){
   return  1;}//等价于hashcode无效
这样做的效果就是在比较哈希码的时候不能进行判断,因为每个对象返回的哈希码都是1,每次都必须要经过比较equals()方法后才能进行判断是否重复,这当然会引起效率的大大降低。


--------------------------------------------------------------------------------

clone
protected Object clone()
                throws CloneNotSupportedException创建并返回此对象的一个副本。“副本”的准确含义可能依赖于对象的类。一般来说,对于任何对象 x,如果表达式:
x.clone() != x是正确的,则表达式:
x.clone().getClass() == x.getClass()将为 true,但这些不是绝对条件。一般情况下是:
x.clone().equals(x)将为 true,但这不是绝对条件。
按照惯例,返回的对象应该通过调用 super.clone 获得。如果一个类及其所有的超类(Object 除外)都遵守此约定,则 x.clone().getClass() == x.getClass()。

按照惯例,此方法返回的对象应该独立于该对象(正被克隆的对象)。要获得此独立性,在 super.clone 返回对象之前,有必要对该对象的一个或多个字段进行修改。这通常意味着要复制包含正在被克隆对象的内部“深层结构”的所有可变对象,并使用对副本的引用替换对这些对象的引用。如果一个类只包含基本字段或对不变对象的引用,那么通常不需要修改 super.clone 返回的对象中的字段。

Object 类的 clone 方法执行特定的克隆操作。首先,如果此对象的类不能实现接口 Cloneable,则会抛出 CloneNotSupportedException。注意:所有的数组都被视为实现接口 Cloneable。否则,此方法会创建此对象的类的一个新实例,并像通过分配那样,严格使用此对象相应字段的内容初始化该对象的所有字段;这些字段的内容没有被自我克隆。所以,此方法执行的是该对象的“浅表复制”,而不“深层复制”操作。

Object 类本身不实现接口 Cloneable,所以在类为 Object 的对象上调用 clone 方法将会导致在运行时抛出异常。


返回:
此实例的一个克隆。
抛出:
CloneNotSupportedException - 如果对象的类不支持 Cloneable 接口,则重写 clone 方法的子类也会抛出此异常,以指示无法克隆某个实例。
另请参见:
Cloneable

--------------------------------------------------------------------------------

toString
public String toString()返回该对象的字符串表示。通常,toString 方法会返回一个“以文本方式表示”此对象的字符串。结果应是一个简明但易于读懂。建议所有子类都重写此方法。
Object 类的 toString 方法返回一个字符串,该字符串由类名(对象是该类的一个实例)、at 标记符“@”和此对象哈希码的无符号十六进制表示组成。换句话说,该方法返回一个字符串,它的值等于:

getClass().getName() + '@' + Integer.toHexString(hashCode())

返回:
该对象的字符串表示形式。

--------------------------------------------------------------------------------

notify
public final void notify()唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性的,并在对实现做出决定时发生。线程通过调用其中一个 wait 方法,在对象的监视器上等待。
直到当前的线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争;例如,唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣势。

此方法只应由作为此对象监视器的所有者的线程来调用。通过以下三种方法之一,线程可以成为此对象监视器的所有者:

通过执行此对象的同步 (Sychronized) 实例方法。
通过执行在此对象上进行同步的 synchronized 语句的正文。
对于 Class 类型的对象,可以通过执行该类的同步静态方法。
一次只能有一个线程拥有对象的监视器。


抛出:
IllegalMonitorStateException - 如果当前的线程不是此对象监视器的所有者。
另请参见:
notifyAll(), wait()

--------------------------------------------------------------------------------

notifyAll
public final void notifyAll()唤醒在此对象监视器上等待的所有线程。线程通过调用其中一个 wait 方法,在对象的监视器上等待。
直到当前的线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争;例如,唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣势。

此方法只应由作为此对象监视器的所有者的线程来调用。请参阅 notify 方法,了解线程能够成为监视器所有者的方法的描述。


抛出:
IllegalMonitorStateException - 如果当前的线程不是此对象监视器的所有者。
另请参见:
notify(), wait()

--------------------------------------------------------------------------------

wait
public final void wait(long timeout)
                throws InterruptedException导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量。
当前的线程必须拥有此对象监视器。

此方法导致当前线程(称之为 T)将其自身放置在对象的等待集中,然后放弃此对象上的所有同步要求。出于线程调度目的,线程 T 被禁用,且处于休眠状态,直到发生以下四种情况之一:

其他某个线程调用此对象的 notify 方法,并且线程 T 碰巧被任选为被唤醒的线程。
其他某个线程调用此对象的 notifyAll 方法。
其他某个线程中断线程 T。
已经到达指定的实际时间。但是,如果 timeout 为零,则不考虑实际时间,该线程将一直等待,直到获得通知。
然后,从对象的等待集中删除线程 T,并重新进行线程调度。然后,该线程以常规方式与其他线程竞争,以获得在该对象上同步的权利;一旦获得对该对象的控制权,该对象上的所有其同步声明都将被还原到以前的状态 - 这就是调用 wait 方法时的情况。然后,线程 T 从 wait 方法的调用中返回。所以,从 wait 方法返回时,该对象和线程 T 的同步状态与调用 wait 方法时的情况完全相同。
在没有被通知、中断或超时的情况下,线程还可以唤醒一个所谓的虚假唤醒 (spurious wakeup)。虽然这种情况在实践中很少发生,但是应用程序必须通过以下方式防止其发生,即对应该导致该线程被提醒的条件进行测试,如果不满足该条件,则继续等待。换句话说,等待应总是发生在循环中,如下面的示例:

synchronized (obj) {
while (<condition does not hold>)
obj.wait(timeout);
... // Perform action appropriate to condition
     }
(有关这一主题的更多信息,请参阅 Doug Lea 撰写的《Concurrent Programming in Java (Second Edition)》(Addison-Wesley, 2000) 中的第 3.2.3 节或 Joshua Bloch 撰写的《Effective Java Programming Language Guide》(Addison-Wesley, 2001) 中的第 50 项。
如果当前线程在等待时被其他线程中断,则会抛出 InterruptedException。在按上述形式恢复此对象的锁定状态时才会抛出此异常。

注意,由于 wait 方法将当前的线程放入了对象的等待集中,所以它只能解除此对象的锁定;可以同步当前线程的任何其他对象在线程等待时仍处于锁定状态。

此方法只应由作为此对象监视器的所有者的线程来调用。请参阅 notify 方法,了解线程能够成为监视器所有者的方法的描述。


参数:
timeout - 要等待的最长时间(以毫秒为单位)。
抛出:
IllegalArgumentException - 如果超时值为负。
IllegalMonitorStateException - 如果当前的线程不是此对象监视器的所有者。
InterruptedException - 如果在当前线程等待通知之前或者正在等待通知时,另一个线程中断了当前线程。在抛出此异常时,当前线程的中断状态 被清除。
另请参见:
notify(), notifyAll()

--------------------------------------------------------------------------------

wait
public final void wait(long timeout,
                       int nanos)
                throws InterruptedException导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量。
此方法类似于一个参数的 wait 方法,但它允许更好地控制在放弃之前等待通知的时间量。用毫微秒度量的实际时间量可以通过以下公式计算出来:

1000000*timeout+nanos在其他所有方面,此方法执行的操作与带有一个参数的 wait(long) 方法相同。需要特别指出的是,wait(0, 0) 与 wait(0) 相同。

当前的线程必须拥有此对象监视器。该线程发布对此监视器的所有权,并等待下面两个条件之一发生:

其他线程通过调用 notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来。
timeout 毫秒值与 nanos 毫微秒参数值之和指定的超时时间已用完。
然后,该线程等到重新获得对监视器的所有权后才能继续执行。

对于某一个参数的版本,实现中断和虚假唤醒是有可能的,并且此方法应始终在循环中使用:

synchronized (obj) {
while (<condition does not hold>)
obj.wait(timeout, nanos);
... // Perform action appropriate to condition
     }
此方法只应由作为此对象监视器的所有者的线程来调用。请参阅 notify 方法,了解线程能够成为监视器所有者的方法的描述。

参数:
timeout - 要等待的最长时间(以毫秒为单位)。
nanos - 额外时间(以毫微秒为单位,范围是 0-999999)。
抛出:
IllegalArgumentException - 如果超时值是负数,或者毫微秒值不在 0-999999 范围内。
IllegalMonitorStateException - 如果当前线程不是此对象监视器的所有者。
InterruptedException - 如果在当前线程等待通知之前或者正在等待通知时,其他线程中断了当前线程。在抛出此异常时,当前线程的中断状态 被清除。

--------------------------------------------------------------------------------

wait
public final void wait()
                throws InterruptedException导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。换句话说,此方法的行为就好像它仅执行 wait(0) 调用一样。
当前的线程必须拥有此对象监视器。该线程发布对此监视器的所有权并等待,直到其他线程通过调用 notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来。然后该线程将等到重新获得对监视器的所有权后才能继续执行。

对于某一个参数的版本,实现中断和虚假唤醒是可能的,而且此方法应始终在循环中使用:

synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
     }
此方法只应由作为此对象监视器的所有者的线程来调用。请参阅 notify 方法,了解线程能够成为监视器所有者的方法的描述。

抛出:
IllegalMonitorStateException - 如果当前的线程不是此对象监视器的所有者。
InterruptedException - 如果在当前线程等待通知之前或者正在等待通知时,另一个线程中断了当前线程。在抛出此异常时,当前线程的中断状态 被清除。
另请参见:
notify(), notifyAll()

--------------------------------------------------------------------------------

finalize
protected void finalize()
                 throws Throwable当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。子类重写 finalize 方法,以配置系统资源或执行其他清除。
finalize 的常规协定是:当 JavaTM 虚拟机已确定尚未终止的任何线程无法再通过任何方法访问此对象时,将调用此方法,除非由于准备终止的其他某个对象或类的终结操作执行了某个操作。finalize 方法可以采取任何操作,其中包括再次使此对象对其他线程可用;不过,finalize 的主要目的是在不可撤消地丢弃对象之前执行清除操作。例如,表示输入/输出连接的对象的 finalize 方法可执行显式 I/O 事务,以便在永久丢弃对象之前中断连接。

Object 类的 finalize 方法执行非特殊性操作;它仅执行一些常规返回。Object 的子类可以重写此定义。

Java 编程语言不保证哪个线程将调用某个给定对象的 finalize 方法。但可以保证在调用 finalize 时,调用 finalize 的线程将不会持有任何用户可见的同步锁定。如果 finalize 方法抛出未捕获的异常,那么该异常将被忽略,并且该对象的终结操作将终止。

在启用某个对象的 finalize 方法后,将不会执行进一步操作,直到 Java 虚拟机再次确定尚未终止的任何线程无法再通过任何方法访问此对象,其中包括由准备终止的其他对象或类执行的可能操作,在执行该操作时,对象可能被丢弃。

对于任何给定对象,Java 虚拟机最多只调用一次 finalize 方法。

finalize 方法抛出的任何异常都会导致此对象的终结操作停止,但可以通过其他方法忽略它。


抛出:
Throwable - 此方法抛出的 Exception
分享到:
评论

相关推荐

    java.lang.IllegalArgumentException Cannot format given Object as a Date

    在Java编程中,`java.lang.IllegalArgumentException` 是一个标准的运行时异常,它通常表示一个方法接收到的参数值不在预期范围内或者不合法。当尝试将一个无法转换为日期的对象格式化时,就会抛出"Cannot format ...

    java.lang.runtimeexception unexpected subelement

    在Java编程中,`java.lang.RuntimeException` 是一个非检查异常(unchecked exception),它表示程序运行时出现的不正常情况。通常,这类异常是由于程序员的错误或代码逻辑的疏忽造成的,例如类型转换错误、空指针...

    WebLogic错误 java.lang.AssertionError: Registered more than one

    Caused by: java.lang.RuntimeException: javax.management.remote.JMXServerErrorException: java.lang.AssertionError: Registered more than one instance with the same objectName : com.bea:Name=wl04,Type=...

    Java.lang.reflect 包下常用的类及方法简介

    在Java编程语言中,`java.lang.reflect`包是核心库的一部分,它提供了运行时访问类、接口、字段和方法的能力。这个包对于理解和操作对象的动态特性至关重要,尤其是在实现反射机制时。反射允许我们在程序运行期间...

    java.lang包介绍

    `java.lang`包中最基本的类是`Object`,它是所有类层次结构的根,而`Class`类的实例则代表运行时的类。 `java.lang`包包括以下关键类: 1. **Boolean**: 表示布尔值`true`和`false`。 2. **Long, Short, Byte, ...

    android java.lang.IllegalArgumentException contains a path separator

    在Android开发中,Java编程时常会遇到`java.lang.IllegalArgumentException`异常,这通常表示传入的参数不符合方法的要求。在本例中,错误信息“contains a path separator”提示我们问题可能与路径分隔符有关,这...

    Java总结篇系列:java.lang.Object

     Java作为一个庞大的知识体系,涉及到的知识点繁多,本文将从Java中基本的类java.lang.Object开始谈起。  Object类是Java中其他所有类的祖先,没有Object类Java面向对象无从谈起。作为其他所有类的基类,Object...

    java.lang包

    `Object`类是所有Java类的最终超类,包含所有对象共有的属性和方法,如`equals()`比较两个对象是否相等,`hashCode()`返回对象的哈希码,`toString()`返回对象的字符串表示。 通过理解并熟练使用`java.lang`包中的...

    java.lang.NoSuchMethodException: .getPortClassMap()

    在给出的标题 "java.lang.NoSuchMethodException: .getPortClassMap()" 中,异常指向了 `getPortClassMap()` 这个方法,暗示在程序运行时,尝试访问或调用的这个方法在相应的类中没有被找到。 `getPortClassMap` ...

    java.lang包.ppt

    了解 java.lang 包 掌握包装类 掌握String 和 StringBuffer 类 运用以下类的方法: Math Class Object

    在Java中异常分析

    - **异常路径**:`java.lang.Object -&gt; java.lang.Throwable -&gt; java.lang.Exception -&gt; java.lang.RuntimeException -&gt; java.lang.IndexOutOfBoundsException -&gt; java.lang.ArrayIndexOutOfBoundsException` ...

    java.lang.ClassNotFoundException: org.jdom.input.SAXBuilder 处理

    总之,解决“java.lang.ClassNotFoundException: org.jdom.input.SAXBuilder”问题的关键在于确保JDOM库被正确地包含在类路径中,同时检查代码中涉及的类名拼写是否准确。了解并熟练使用SAXBuilder可以帮助开发者...

    java.lang.object源码-finalize-:个人博客(http://bit.ly/javafinalize)上java.lang

    java.lang.object原始码最终不推荐使用java.lang.Object.finalize() 我的博客文章中的示例的Gradle源代码存储库。 在Linux Mint(SUSE Linux)上构建和测试。 由于gradle当前不支持Java 11,因此可以使用标准Java...

    jdbc 帮助类 java 自带连接池 v1.01

    boolean delete(java.lang.String sql, java.util.Map&lt;java.lang.Integer,java.lang.Object&gt; elements) 根据传入的参数删除单条记录的方法 boolean delete(java.lang.String sql, java.lang.Object[] elements)...

    java jdbc帮助类 v1.0 自带连接池

    boolean delete(java.lang.String sql, java.util.Map&lt;java.lang.Integer,java.lang.Object&gt; elements) 根据传入的参数删除单条记录的方法 boolean delete(java.lang.String sql, java.lang.Object[] elements)...

    java.lang.ClassCastException

    在Java编程中,`java.lang.ClassCastException`是一个运行时异常,通常发生在强制类型转换时,如果尝试将一个对象转换为其非兼容类型时就会抛出。这个异常表明在编译时可能成功的类型转换,在运行时被证明是错误的。...

    Java类库复习——java.lang.String

    在Java编程语言中,`java.lang.String`是最重要的类之一,它是所有字符串操作的基础。这个类位于核心类库中,因此无需显式导入即可使用。本文将深入探讨`String`类的一些关键知识点,包括它的特性、构造方法、常用...

    java.lang研究

    `Object`类是所有Java类的根,它定义了所有对象共有的行为,如`equals()`、`hashCode()`和`toString()`方法。`System`类提供了系统级的服务,如标准输入、输出流,以及全局变量`out`、`err`和`in`。 `Thread`类是多...

    javax.activation.UnsupportedDataTypeException: no object DCH for MIME type

    在Oracle 11.2.0.4中调用 javax.mail 发送邮件时...EXEC dbms_java.grant_permission( '&lt;your_schema_please_change&gt;','SYS:java.lang.RuntimePermission', 'setContextClassLoader', '' ); 第二步:解决方案看文档中。

Global site tag (gtag.js) - Google Analytics