Class Overview(类概述)
这个类是 Java 类等级中的根。所有非初级的类型(包括数组)都是直接或间接继承这个类。
按照以下这种风格写一个规范的 equals 方法:
// Use @Override to avoid accidental overloading.
// 使用@Override 为了避免意外的过载
@Override public boolean equals(Object o) {
// Return true if the objects are identical.
// (This is just an optimization, not required for correctness.)
// 如果对象是相同的就返回 true
// (这仅仅是一种优化,并不要求正确性。)
if (this == o) {
return true;
}
// Return false if the other object has the wrong type.
// This type may be an interface depending on the interface's specification.
// 如果另一个对象的类型有误,则返回 false
// 这种类型可能是一个接口,取决于接口的规格
if (!(o instanceof MyType)) {
return false;
}
// Cast to the appropriate type.
// This will succeed because of the instanceof, and lets us access private fields.
// 转换成适当的类型
// 这将是成功的因为 o 是 Mytype 的实例,我们访问私有字段
MyType lhs = (MyType) o;
// Check each field. Primitive fields, reference fields, and nullable reference
// fields are all treated differently.
// 检查每一个字段。原始的字段,参考的字段,空引用的字段都被看成是不同的。
return primitiveField == lhs.primitiveField &&
referenceField.equals(lhs.referenceField) &&
(nullableField == null ? lhs.nullableField == null
: nullableField.equals(lhs.nullableField));
}
如果要重写 equals 方法,同时也应该重写 hashCode 方法:相同的实例必须要有相同的哈希值。
参考 Effcetive Java 里的第 8 条,有更详细的说明。
按照以下这种风格写一人规范的 hashCode 方法:
@Override public int hashCode() {
// Start with a non-zero constant.
// 开始于一个非零常数
int result = 17;
// Include a hash for each field.
// 包括每一个字段的哈希值
result = 31 * result + (booleanField ? 1 : 0);
result = 31 * result + byteField;
result = 31 * result + charField;
result = 31 * result + shortField;
result = 31 * result + intField;
result = 31 * result + (int) (longField ^ (longField >>> 32));
result = 31 * result + Float.floatToIntBits(floatField);
long doubleFieldBits = Double.doubleToLongBits(doubleField);
result = 31 * result + (int) (doubleFieldBits ^ (doubleFieldBits >>> 32));
result = 31 * result + Arrays.hashCode(arrayField);
result = 31 * result + referenceField.hashCode();
result = 31 * result +
(nullableReferenceField == null ? 0
: nullableReferenceField.hashCode());
return result;
}
如果不打算将您的类型用作哈希键, 也不要只依赖于默认的 hashCode 方法实现。因为这样会不明显的破坏将来任何一个把该类型做为哈希键的编码。应该用抛异常的方法来替代:
@Override public int hashCode() {
throw new UnsupportedOperationException();
}
参考 Effective Java 第 9 条,有更详细的说明。
为了调试方便,按照以下的风格重写 toString 是很常见的:
@Override public String toString() {
return getClass().getName() + "[" +
"primitiveField=" + primitiveField + ", " +
"referenceField=" + referenceField + ", " +
"arrayField=" + Arrays.toString(arrayField) + "]";
}
包含的字段集一般与用 equals 方法测试的字段是一样的。
参考 Effective Java 第 10 条,有更详细的说明。
Public Constructors(公共构造方法)
public Object()
构造一个新的 Object 实例。
Public Methods(公共方法)
public boolean equals(Object o)
比较该实例与指定的对象,并且指示它们是否相同。为了相同,o 必须使用特定的类比较来表示与此实例相同的对象。
通用约定是,这种比较应该是自反性,对称性,传递性。除了 null,没有引用的对象等于 null。
仅仅当 this==o 的时候默认返回 true。如果想要实现自己的 equals 方法,参考写一个正确的 equals 方法。
对于 equals 方法和 hashCode 方法来说,通用约定是,如果两个对象根据 equals 方法比较是相等的,那么调用这两个对象中任意一个对象的 hashCode 方法都必须产生同样的整数结果。这就意味着,Object 的任意一个子类通常这两个方法都会复写,或者都不复写。
参数
o 与该实例比较的对象。
返回值
如果指定的对象与该对象相同,返回 true ,否则返回 false。
参考
hashCode()
public final Class> getClass()
返回一个唯一的 Class 实例,表示这个对象的类。注意,getClass()是一个特例,它事实上返回Class ,Foo 是对表达式类型的擦除当 getClass()被调用时(这里我也不懂,实在不知道该怎么翻译 > .. <)。
正如这个例子,下面的代码实际上是会可以编译的,虽然有人认为可能不会:
List l = new ArrayList();
Class c = l.getClass();
返回值
该对象类的实例。
public int hashCode()
返回一个该对象的 hash code,根据约定,如果两个对象通过 equals 方法返回 true,那么这两个对象一定会返回相同的 hash code 值。这就意味着 Object 的所有子类都会同时复写这两个方法或是一个全都不复写。
注意,除非用 euqals 比较的信息改变,否则 hash 的值是不会变的。
如果想要实现自己的 hashCode 方法,参考写一个正确的 hashCode 方法.
返回值
该对象的 hash code。
参考
equals(Object)
public final void notify()
由于一个正在等待该对象的监听器的(通过调用 wait() 方法)线程被唤醒。如果正在等待的线程多于一个,VM 会任意选择它们中的一个。被选择的这个线程不会马上执行。该线程调用 notify() 方法先释放该对象的监听器。而且,所选的线程仍要与试图同步在同一对象上的其他线程竞争。
这个方法只能由该对象监听器的线程调用。线程成为该对象监听器的所有者
- 通过执行该对象的同步方法;
- 通过执行同步对象的同步语句的正文;
- 如果对象类型为Class,则通过执行同步静态方法。
参考
notify()
wait()
wait(long)
wait(long,int)
Thread
public final void notifyAll()
由于所有正在等待该对象的监听器的(通过调用 wait() 方法)线程被唤醒。这些线程不会马上执行。线程调用 notify() 方法先释放该对象的监听器。而且,这些线程仍要与试图同步在同一对象上的其他线程竞争。
这个方法只能由该对象监听器的线程调用。线程成为该对象监听器的所有者
- 通过执行该对象的同步方法;
- 通过执行同步对象的同步语句的正文;
- 如果对象类型为Class,则通过执行同步静态方法。
异常
IllegalMonitorStateException(非法监视状态异常) 当调用该方法的线程不是该对象监听器的所有者。
参考
notify()
wait()
wait(long)
wait(long,int)
public String toString()
返回一个简洁的,人类可读的描述该对象的字符串。建议子类复写这个方法,并且提供一个考虑到该对象的类型和数据的实现。默认的实现相当于以下的表达形式:
getClass().getName() + '@' + Integer.toHexString(hashCode())
如果想要实现一个自己的 toString 方法,参见写一个正确的 toString 方法。
返回值
该对象的一个可打印的表达形式。
public final void wait()
由于调用线程时要等到另一个线程调用了该对象的 notify() 或 notifyAll() 方法。该方法只能由该对象的监听器的线程调用,参见 notify() 中如何使一个线程成为监听器的所有者。
一个正在等待的线程可能会由于接受到 interrupt() 而导致提前停止等待,所以 wait 方法应该循环调用,以检查在继续之前已经等待的条件是否已满足。
当线程在等待的时候,它会放弃对该对象的监听器的所有权。当它被通知(或是被中断)时,在开始运行之前它会重新获得监听器。
异常
IlleaglMonitorStateException (非法监视状态异常) 当调用该方法的线程不是该对象的监听所有者。
InterruptedException (中断异常) 如果当前线程已经被中断。在异常抛出之前,当前线程的中断状态会被清除。
参考
notify()
notifyAll()
wait(long)
wait(long,int)
Thread
public final void wait(long millis,int nanos)
由于调用线程时要等到另一个线程调用了该对象的 notify() 或 notifyAll() 方法,或是过了指定的超时时间。该方法只由该对象的监听器的线程调用,参见 notify() 中如何使一个线程成为监听器的所有者。
一个正在等待的线程可能会由于接受到 interrupt() 而导致提前停止等待,所以 wait 方法应该循环调用,以检查在继续之前已经等待的条件是否已满足。
当线程在等待的时候,它会放弃对该对象的监听器的所有权。当它被通知(或是被中断)时,在开始运行之前它会重新获得监听器。
当超时时间为 0 时,表示正在调用的线程应该一直等待,除非被中断或是被通知。
参数
millis 等待的最大时间,以毫秒为单位。
nanos 等待的毫秒数,以纳少为单位。
异常
IllegalArgumentException (非法参数异常) 当 millis < 0,nanos < 0 或 nanos > 999999.
IllegalMonitorStateException (非法监视状态异常) 当调用该方法的线程不是该对象的监听所有者。
InterruptedException (中断异常) 如果当前线程已经被中断。在异常抛出之前,当前线程的中断状态会被清除。
参考
notify()
notifyAll()
wait(long)
wait(long,int)
Thread
public final void wait(long millis)
由于调用线程时要等到另一个线程调用了该对象的 notify() 或 notifyAll() 方法,或是过了指定的超时时间。该方法只由该对象的监听器的线程调用,参见 notify() 中如何使一个线程成为监听器的所有者。
一个正在等待的线程可能会由于接受到 interrupt() 而导致提前停止等待,所以 wait 方法应该循环调用,以检查在继续之前已经等待的条件是否已满足。
当线程在等待的时候,它会放弃对该对象的监听器的所有权。当它被通知(或是被中断)时,在开始运行之前它会重新获得监听器。
当超时时间为 0 时,表示正在调用的线程应该一直等待,除非被中断或是被通知。
参数
millis 等待的最大时间,以毫秒为单位。
异常
IllegalArgumentException (非法参数异常) 当 millis < 0,nanos < 0 或 nanos > 999999.
IllegalMonitorStateException (非法监视状态异常) 当调用该方法的线程不是该对象的监听所有者。
InterruptedException (中断异常) 如果当前线程已经被中断。在异常抛出之前,当前线程的中断状态会被清除。
参考
notify()
notifyAll()
wait(long)
wait(long,int)
Thread
Protected Methods(被保护的方法)
protected Object clone()
创造并返回该对象的一个副本。默认的实现返回一个所谓的浅的("shallow")的副本:它创建一个同类的新的实例,然后从该实例复制字段值(包括对象的引用)到新的实例。相反,“深”副本(deep)还会递归地克隆嵌套对象。需要实现这种克隆的子类应该调用 super.clone()来创建新的实例,然后创建嵌套的可变对象的深层副本。
返回值
该对象的副本。
异常
CloneNotSupportedException (克隆不支持异常) 如果该对象的类不能实现 Cloneable 接口。
protected void finalize()
当垃圾收集器检测到该实例不再是可获得的时调用。默认不做任何操作,但为了释放资源该方法可以被复写。
注意,重写该方法的对象比不重写更消耗资源。当该对象是不可获得的之后的终结器可能还会运行一段时间,这个由内存的压力决定,所以通过它们进行清理不是好的做法。另外,终结器运行在单个VM范围的终结器线程上,因此在终结器中时行模块化工作不是好的做法。终结器通常只需要有一个类,那个类有一个本地对等全,并且需要调用一个本地的方法去销毁本地对等体。即便这样,提供一个明确的关闭方法(并实现 Closeable 接口)是好的做法,并且坚持通过手动调用处理实例。这对于像文件这样的东西效果很好,但对于像 BigInteger 这样的东西来说,不是很好,那些典型的调用代码必须处理大量的临时文件。不幸的是,从单个终结器线程的角度来看,创建大量临时文件的代码是最差的代码。
如果必须使用终结器,要考虑至少提供一个自己的 ReferenceQueue 并且有自己的线程来处理这个 queue。
与构造函数不一样,终结器没有自动链接。需要自己调用 super.finalize()。
由终结器抛出的未捕获的异常被忽略,不终止终结器的线程。参考 Effective Java 第 7 条,有更详细的说明。
异常
Throwable