java.lang.Object源码阅读笔记

一、官方文档的描述
1. getClass()
public final native Class<?> getClass();

Class {@code Object} is the root of the class hierarchy. Every class has {@code Object} as a superclass. All objects, including arrays, implement the methods of this class.

Object类是类层次结构的根。每个类以Object类为父类。所有的对象,包括数组,都实现了这个类的方法。

#### 2. hashCode()
    public native int hashCode();

Returns a hash code value for the object. This method is supported for the benefit of hash tables such as those provided by {@link java.util.HashMap}.

为该对象返回一个哈希码。这个方法支持哈希表的好处,比如java.util.HashMap提供的哈希表。

The general contract of {@code hashCode} is:

哈希表的一般要求是:

  • Whenever it is invoked on the same object more than once during an execution of a Java application, the {@code hashCode} method must consistently return the same integer, provided no information used in {@code equals} comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.

    无论何时,在执行一个Java程序时,对于同一个对象hashCode方法的多次调用,hashCode方法必须返回相同的值,前提是在比较两个对象时的信息没有变化。这个值不需要在程序切换执行期间保持一致。

  • If two objects are equal according to the {@code equals(Object)} method, then calling the {@code hashCode} method on each of the two objects must produce the same integer result.

    如果根据equals(Object)方法两个对象相等,那么就在对这两个对象调用hashCode方法时产生的值将是相同的。

  • It is not required that if two objects are unequal according to the {@link java.lang.Object#equals(java.lang.Object)} method, then calling the {@code hashCode} method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.

    如果根据equals(Object)方法两个对象不相等,并不要求对这两个对象调用hashCode方法时产生的值必须不同。然而,程序员应当知道,对不相等的对象产生不同的值可以提高哈希表的性能。

As much as is reasonably practical, the hashCode method defined by class {@code Object} does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the Java™ programming language.)

为了尽可能的合理可行,hashCode方法被Object类定义为为不同的对象返回不同的整数值。(这通常通过将对象的内部地址转换为整数来实现,但是这种实现技术不是Java语言所要求的)

#### 3. equals() Indicates whether some other object is “equal to” this one. 表明其他的对象是否与这个对象相等

The {@code equals} method implements an equivalence relation on non-null object references:

equals方法对非空对象的引用实现了等价关系

  • It is reflexive: for any non-null reference value {@code x}, {@code x.equals(x)} should return {@code true}.

    自反性:对于任何非空的引用 xx.equals(x)都应返回true

  • It is symmetric: for any non-null reference values {@code x} and {@code y}, {@code x.equals(y)} should return {@code true} if and only if {@code y.equals(x)} returns {@code true}.

    对称性:对于任何非空的引用xy,当且仅当y.equals(x)返回true时,x.equals(y)应返回true

  • It is transitive: for any non-null reference values {@code x}, {@code y}, and {@code z}, if {@code x.equals(y)} returns {@code true} and {@code y.equals(z)} returns {@code true}, then {@code x.equals(z)} should return {@code true}.

    传递性:对于任何非空的引用xyz ,如果x.equals(y)返回true并且y.equals(z),那么 x.equals(z)也返回true

  • It is consistent: for any non-null reference values {@code x} and {@code y}, multiple invocations of {@code x.equals(y)} consistently return {@code true} or consistently return {@code false}, provided no information used in {@code equals} comparisons on the objects is modified.

    一致性:对于任何非空的引用xy,多次连续调用 x.equals(y)返回true,或连续返回false,对于已修改的对象,不提供equals得比较信息

  • For any non-null reference value {@code x},
    {@code x.equals(null)} should return {@code false}.

对于任何非空的引用xx.equals(null)返回false

The {@code equals} method for class {@code Object} implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values {@code x} and {@code y}, this method returns {@code true} if and only if {@code x} and {@code y} refer to the same object ({@code x == y} has the value {@code true}).

Object类的equals方法实现对象上最可能的等价关系;即,对于任何非空的引用xy,这个方法当且仅当xy都指向同一个对象x == y时返回true Note that it is generally necessary to override the {@code hashCode} method whenever this method is overridden, so as to maintain the general contract for the {@code hashCode} method, which states that equal objects must have equal hash codes.

注意,当这个方法被覆盖时,通常必须重写hashCode方法,这是为了维持hashCode声明的规约:相等的对象必须拥有相同的哈希码 ———

#### 二、思考 #### 1. 对于hashCode()方法 - 作用:产生哈希码 - 该方法有一条规约: 对同一个对象多次调用该方法,该方法必须返回相同的哈希码(前提是在比较时对象没有变化)。 #### 2. 对于equals()方法 - 作用:判断两个对象是否相等 - 四个性质(同时也是重写的原则): 1. **自反性**: 对于非空对象 x,它与自己比较时,即 x.equals(x)应返回 true 2. **对称性**: 对于非空对象 xy,当且仅当 y.equals(x)返回 true时, x.equals(y)返回 true 3. **传递性**: 就是如果非空对象x,y相等,y,z相等,则对象x,z相等 4. **一致性**: 对于非空对象 xy,只要该方法比较的对象没有改变,那么多次连续调用 x.equals(y)都会返回相同的结果 - **注意**: 重写 equals()后必须重写 hashCode() 这是为什么呢? 这是为了维持 hashCode声明的规约:相等的对象必须拥有相同的哈希码 为什么要维持这个规约? 我们知道,在一些集合中,比如Set和Map,元素是无序的,所以这些集合中的元素不能重复。那么我们在放入元素的时候,那他是怎么知道我们放的元素是不是和里面已有的元素重复呢?也许我们会想到,他可能是一个个比较得来的,但是这样显然效率非常低,比如Set里面有成千上万个元素,直接遍历的话显然是效率低下的。所以就有人想出了哈希算法来提高在集合中查找的效率。 比如,我们来看HashMap中put的部分代码
    public V put(K key, V value) {
    // 计算当前key的hash值
        return putVal(hash(key), key, value, false, true);
    }

    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i;
        // 判断表是否为空
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
            // 判断当前位置是不是空的
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
        else {
        // 如果当前位置已经有了key
            Node<K,V> e; K k;
            // 判断当前key和该位置已有的那个key是不是重复,如果重复就覆盖
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;
                // 判断是不是TreeNode
            else if (p instanceof TreeNode)
                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
            else {
            // 不是TreeNode,则直接遍历链表
                for (int binCount = 0; ; ++binCount) {
                    if ((e = p.next) == null) {
                        p.next = newNode(hash, key, value, null);
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash);
                        break;
                    }
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
                }
            }
            ......

我们可以看到,在put时,HashMap先通过hashCode()方法计算出hash值,然后根据hash值计算出索引位置,如果这个位置已经有元素了,这时就需要使用到equals()去判断当前要放的key和已有的key是不是相同,然后再做相应的处理。

在这些集合中,用equals判断两个对象内容相等,但是如果没覆写hashCode()方法,那么hashCode()只是返回当前对象的地址的int类型的值,而两个对象肯定是地址不通过,那么用hashCode()返回的值肯定也不同,那么就会导致使用这些map进行操作的时候出错。

3. equals()和hashCode()的关系
  • 如果x.equals(y)返回true,则说明两个对象相等,那么这两个对象的hashCode()返回的值也必须相等。
  • 如果x.equals(y)返回false,则说明两个对象不相等,那么这两个对象的hashCode()返回的值可能相等,也可能不相等。对于这一点,我是这样理解的,因为hashCode()返回的是一个int类型的值,int型是32位、有符号的以二进制补码表示的整数,假设int型能表示n个数字,那么也就是说hashCode()能表示n个不同的元素,但是对象可能有n + 1个,那么这第n + 1个对象只能被之前那n个数字中的某一个表示,因此就出现了相同的hashCode值表示了两个不同的对象的情况,也就是对两个不同的对象调用hashCode()方法返回的值有可能不同。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值