裸泳的猪

沾沾自喜其实最可悲

0%

Java基础提升_Object

Object类 是类层次结构的根类。

Object类是所有类的超类。所有对象(包括数组)都实现这个类的方法。

所以需要了解Object类的所有方法:

1.hashCode()

1
public int hashCode()

返回该对象的哈希码值。默认情况下,该方法会根据对象的地址来计算。
不同对象的 hashCode() 的值一般是不相同。但是,同一个对象的hashCode() 值肯定相同。

2.getClass()

1
public final Class getClass()

返回此 Object 的运行时类。

2.1.getName()

可以通过 Class 类中的一个方法,获取对象的真实类的全名称。

1
2
3
Object obj = new Object();
Class c1 = obj.getClass();
String name =c1.getName();

3.toString()

getClass().getName() + “@” + Integer.toHexString(hashCode()) 这返回的是:类的全路径名称+它的哈希码值在实际的开发中对我们来说是没有意义的所以我们一般会重写该方法

1
2
3
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

4.equals()

1
2
3
public boolean equals(Object obj) {
return (this == obj);
}

默认方法是比较的是对象的引用是否相同。由于比较对象的引用对于我们在实际开发中没有意义,一般还是要重写该方法。 一般来说基础类型用==,比较引用数据类型使用equals

5.wait()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/* 使当前线程等待,直到另一个线程为此对象调用notify()方法或notifyAll()方法,或者经过了指定的时间。
当前线程必须拥有该对象的监视器。
此方法使当前线程(称为T )将自己置于该对象的等待集中,然后放弃对该对象的任何和所有同步声明。 出于线程调度的目的,线程T被禁用,并且处于休眠状态,直到发生以下四种情况之一:
其他一些线程为此对象调用notify方法,并且线程T恰好被任意选择为要唤醒的线程。
其他一些线程为此对象调用notifyAll方法。
其他一些线程中断线程T。
指定的实时量或多或少已经过去。 但是,如果timeout为零,则不考虑实时,线程只是等待直到通知。
然后将线程T从该对象的等待集中删除,并重新启用线程调度。 然后,它以通常的方式与其他线程竞争在对象上进行同步的权利。 一旦它获得了对象的控制权,它对对象的所有同步声明都将恢复到原样-即,恢复到调用wait方法时的情况。 然后,线程T从调用wait方法返回。 因此,从wait方法返回时,对象和线程T的同步状态与调用wait方法时的状态完全相同。
线程也可以被唤醒,而不会被通知,中断或超时,即所谓的虚假唤醒。 尽管在实践中这种情况很少发生,但是应用程序必须通过测试应该导致线程唤醒的条件来防范它,并在条件不满足时继续等待。 换句话说,等待应该总是在循环中发生,就像这样:
synchronized (obj) {
while (<condition does not hold>)
obj.wait(timeout);
... // Perform action appropriate to condition
}

(有关此主题的更多信息,请参见Doug Lea的“ Java并发编程(第二版)”(Addison-Wesley,2000年)中的3.2.3节,或Joshua Bloch的“有效的Java编程语言指南”(Addison-卫斯理(Wesley),2001年)。
如果当前线程被中断任何线程之前或在等待时,那么InterruptedException被抛出。 如上所述,直到该对象的锁定状态恢复之前,不会引发此异常。
请注意, wait方法将当前线程放入该对象的等待集中,因此只会解锁该对象; 当线程等待时,当前线程可以在其上同步的所有其他对象保持锁定。
此方法只能由作为该对象的监视器的所有者的线程调用。 有关线程可以成为监视器所有者的方式的描述,请参见notify方法。
参数:
超时–等待的最长时间(以毫秒为单位)。

IllegalArgumentException如果超时值为负。
IllegalMonitorStateException如果当前线程不是对象监视器的所有者。
InterruptedException如果任何线程在当前线程等待通知之前或之时中断了当前线程。 引发此异常时,将清除当前线程的中断状态。
请参见:
notify() , notifyAll() */
public final native void wait(long timeout) throws InterruptedException;

5.1-notify()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*唤醒正在此对象的监视器上等待的单个线程。 
如果有任何线程在此对象上等待,则选择其中一个唤醒。
**该选择是任意**的,并且可以根据实现情况进行选择。
线程通过调用其中一个wait方法在对象的监视器上wait 。

在当前线程放弃对该对象的锁定之前,唤醒的线程将无法继续。
唤醒的线程将以通常的方式与可能正在主动竞争以在此对象上进行同步的任何
其他线程竞争。 例如,被唤醒的线程在成为锁定该对象的下一个线程时没有任
何可靠的特权或劣势。

此方法只能由作为该对象的监视器的所有者的线程调用。
线程通过以下三种方式之一成为对象监视器的所有者:
- 通过执行该对象的同步实例方法。
- 通过执行在对象上synchronized语句的主体。
- 对于Class,类型的对象Class,通过执行该类的同步静态方法。

一次只能有一个线程拥有对象的监视器。
throw IllegalMonitorStateException如果当前线程不是此对象的监视器的所有者。
请参见:
notifyAll() , wait()*/
public final native void notify();

5.2-notifyAll()

1
2
3
4
5
6
7
8
9
/* 唤醒正在此对象的监视器上等待的所有线程。 线程通过调用其中一个wait方法在对象的监视器上wait 。
在当前线程放弃对该对象的锁定之前,唤醒的线程将无法继续。 唤醒的线程将以通常的方式与任何其他可能正在主动竞争以在此对象上进行同步的线程竞争。 例如,被唤醒的线程在成为锁定该对象的下一个线程时没有任何可靠的特权或劣势。
此方法只能由作为该对象的监视器的所有者的线程调用。 有关线程可以成为监视器所有者的方式的描述,请参见notify方法。

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

public final native void notifyAll();

6.finalize()

finalize()是Object中的方法,当垃圾回收器将要回收对象所占内存之前被调用,即当一个对象被虚拟机宣告死亡时会先调用它finalize()方法,让此对象处理它生前的最后事情(这个对象可以趁这个时机挣脱死亡的命运)。

1
2
3
4
5
6
7
8
9
10
11
12
/* 当垃圾回收确定不再有对该对象的引用时,由垃圾回收器在对象上调用。 子类覆盖finalize方法以处置系统资源或执行其他清除。
finalize的一般约定是,当Java™虚拟机确定不再有任何手段可以使尚未死亡的任何线程访问该对象时(除非是由于操作而导致),调用finalize由完成的其他某些对象或类的完成确定。 finalize方法可以采取任何措施,包括使该对象可再次用于其他线程。 但是, finalize的通常目的是在清除对象之前将其清除。 例如,代表输入/输出连接的对象的finalize方法可能会执行显式I / O事务,以在永久丢弃该对象之前中断连接。
Object类的finalize方法不执行任何特殊操作; 它只是正常返回。 Object子类可以覆盖此定义。
Java编程语言不能保证哪个线程将为任何给定对象调用finalize方法。 但是,可以保证,调用finalize的线程在调用finalize时不会持有任何用户可见的同步锁。 如果finalize方法抛出未捕获的异常,则该异常将被忽略,并且该对象的终止将终止。
在为对象调用finalize方法之后,在Java虚拟机再次确定不再有任何方法可以使尚未死亡的任何线程访问该对象之前,不采取进一步的措施,包括可能采取的措施可以通过其他准备完成的对象或类来完成,此时可以丢弃该对象。
对于任何给定的对象,Java虚拟机都不会多次调用finalize方法。
由finalize方法引发的任何异常都将导致此对象的终止终止,但否则将被忽略。

Throwable –此方法引发的Exception
请参见:
ref.WeakReference , ref.PhantomReference */
protected void finalize() throws Throwable { }

下面是引申出的一些问题

为什么 wait,notify 和 notifyAll 是在 Object 类中定义的而不是在 Thread 类中定义?

  1. wait 和 notify 不仅仅是普通方法或同步工具,更重要的是它们是 Java 中两个线程之间的通信机制。对语言设计者而言, 如果不能通过 Java 关键字(例如 synchronized)实现通信此机制,同时又要确保这个机制对每个对象可用, 那么 Object 类则是的正确声明位置。记住同步和等待通知是两个不同的领域,不要把它们看成是相同的或相关的。同步是提供互斥并确保 Java 类的线程安全,而 wait 和 notify 是两个线程之间的通信机制。

  2. 每个对象都可上锁,这是在 Object 类而不是 Thread 类中声明 wait 和 notify 的另一个原因。

  3. 在 Java 中为了进入代码的临界区,线程需要锁定并等待锁定,他们不知道哪些线程持有锁,而只是知道锁被某个线程持有, 并且他们应该等待取得锁, 而不是去了解哪个线程在同步块内,并请求它们释放锁定。

  4. Java 是基于 Hoare 的监视器的思想,在Java中,所有对象都有一个监视器。
    线程在监视器上等待,为执行等待,我们需要2个参数:
    一个线程
    一个监视器(任何对象)
    在 Java 设计中,线程不能被指定,它总是运行当前代码的线程。但是,我们可以指定监视器(这是我们称之为等待的对象)。这是一个很好的设计,因为如果我们可以让任何其他线程在所需的监视器上等待,这将导致“入侵”,导致在设计并发程序时会遇到困难。请记住,在 Java 中,所有在另一个线程的执行中侵入的操作都被弃用了(例如 stop 方法)。

-------------本文结束感谢您的阅读-------------