Java Object 对象方法

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

Object的有如下这些方法:

214039_l9qP_1993939.png

Eclipse的类结构,红色是private修饰符,黄色是protected修饰符,绿色是public修饰符。

1.   public final Class<?> getClass()
返回此Object的运行时类。返回的Class对象是由所表示类的 static synchronized方法锁定的对象。
实际结果类型是 Class<? extends |X|>,其中 |X| 表示清除表达式中的静态类型,该表达式调用 getClass。 例如,以下代码片段中不需要强制转换:

Numbe n = 0;
Class<? extends Number> c = n.getClass();
备注:(1) static synchronized 是Class类锁,所有对象共同的一个锁。(2) 是反射的起点,拿到Class对象,拿到了类的一切。

 

2.  public boolean equals(Object obj)

判断 非空对象 是否与某个其他对象“相等”。

equals需要符合一些原则,如下:

自反性:对于非空引用x,x.equals(x)永远返回true;

对称性:对于非空引用值x和y, 如果x.equals(y)返回true,那么y.equals(x)也返回true;

传递性:x.equals(y)是true,y.equals(z)是true,那么x.equals(z)或者z.equals(x)也是true;

一致性:对于任何非空值x和y,在x和y没有修改信息的情况下,x.equals(y)始终返回true或者false;

备注:默认的equals判断就是判断是否是同一个对象(内存同一个地址块代表的对象),如果重写了equals方法,那么必须要重写hashCode方法。因为约定要求,equals相等的对象,hashCode也相同。反过来不做要求,即使equals不等,hashCode也可以一样。

 

3. public int hashCode()

返回该对象的哈希码值。支持此方法是为了提高哈希表(例如 java.util.Hashtable 提供的哈希表)的性能。

hashCode的常规协定:

如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。

如果,重写了类的equals方法,但是不重写hashCode方法,就违反了“常规协定”。

 

 

如何重写hashCode方法呢?

 

1、重写hashcode()的原则

通过前面的描述我们知道,重写hashCode需要遵守以下原则:

(1)如果重写了equals()方法,检查条件“两个对象使用equals()方法判断为相等,则hashCode()方法也应该相等”是否成立,如果不成立,则重写hashCode ()方法。

(2)hashCode()方法不能太过简单,否则哈希冲突过多。

(3)hashCode()方法不能太过复杂,否则计算复杂度过高,影响性能。
2、hashCode()重写方法

《Effective Java》中提出了一种简单通用的hashCode算法

A、初始化一个整形变量,为此变量赋予一个非零的常数值,比如int result = 17;
B、选取equals方法中用于比较的所有域(之所以只选择equals()中使用的域,是为了保证上述原则的第1条),然后针对每个域的属性进行计算:

(1) 如果是boolean值,则计算f ? 1:0
(2) 如果是byte\char\short\int,则计算(int)f
(3) 如果是long值,则计算(int)(f ^ (f >>> 32))
(4) 如果是float值,则计算Float.floatToIntBits(f)
(5) 如果是double值,则计算Double.doubleToLongBits(f),然后返回的结果是long,再用规则(3)去处理long,得到int
(6) 如果是对象应用,如果equals方法中采取递归调用的比较方式,那么hashCode中同样采取递归调用hashCode的方式。否则需要为这个域计算一个范式,比如当这个域的值为null的时候,那么hashCode 值为0
(7) 如果是数组,那么需要为每个元素当做单独的域来处理。java.util.Arrays.hashCode方法包含了8种基本类型数组和引用数组的hashCode计算,算法同上。

C、最后,把每个域的散列码合并到对象的哈希码中。

下面通过一个例子进行说明。在该例中,Person类重写了equals()方法和hashCode()方法。因为equals()方法中只使用了name域和age域,所以hashCode()方法中,也只计算name域和age域。

对于String类型的name域,直接使用了String的hashCode()方法;对于int类型的age域,直接用其值作为该域的hash。

 

4. public String toString()

返回该对象的字符串表示。建议子类重写此方法。

Object 类的 toString 方法返回一个字符串,该字符串由类名(对象是该类的一个实例)、at 标记符“@”和此对象哈希码的无符号十六进制表示组成。换句话说,该方法返回一个字符串,它的值等于:
getClass().getName() + '@' + Integer.toHexString(hashCode())

 

 

6. public final void wait()

7. public final void notify()

8. public final void notifyAll()

以上三个方法是线程的等待和唤醒通知

 

9. protected void finalize()

当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。子类重写 finalize 方法,以配置系统资源或执行其他清除。

 

10. protected Object clone()

创建并返回此对象的一个副本。“副本”的准确含义可能依赖于对象的类。这样做的目的是,对于任何对象 x,表达式:
x.clone() != x为 true,表达式:
x.clone().getClass() == x.getClass()也为 true,但这些并非必须要满足的要求。一般情况下:
x.clone().equals(x)为 true,但这并非必须要满足的要求。

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

转载于:https://my.oschina.net/jrrx/blog/1518344