• Object


    Java 是一门纯面向对象的编程语言,Java 世界里万物皆对象,这些对象的祖宗就是 Object 类了。学习其他类实现的过程中,难免与 Object 打交道,所以这里记录下学习过程中的笔记吧!

    First Blood

    首先是在学习 HashMap、HashTable 的过程中遇到了关于 Object 类的 hashCode 和 equals 这两方法的讨论,那就去看看 JDK 源码里是怎么描述这两个方法的吧:

    /**
         * 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}.
         * <p>
         * The general contract of {@code hashCode} is:
         * <ul>
         * <li>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.
         * <li>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.
         * <li>It is <em>not</em> 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.
         * </ul>
         * <p>
         * 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&trade; programming language.)
         *
         * @return  a hash code value for this object.
         * @see     java.lang.Object#equals(java.lang.Object)
         * @see     java.lang.System#identityHashCode
         */
        public native int hashCode();
    

    注释里先说了 hashCode 方法就是服务于哈希表数据结构类(比如 HashMap),该方法是 JDK 原生方法,具体实现可能随着 JDK 厂商版本不同而不同,所以我们就不去看其具体实现了,就只说说其一般约定吧:

    1. 在同一次运行中的 JVM 里,同一个对象的 hashCode 方法返回值应当一致;不时同一次运行的时,该方法返回值可以不一致;
    2. 如果两个对象通过 equals 方法判等时结果返回真,那么这两个对象调用 hashCode 方法的返回值应该一致;
    3. 两个不同对象调用 hashCode 方法并不强制其返回结果必须不一致,但是其返回结果不一致时哈希表的性能更高;
    4. JDK 实现里,鉴于实用原则,不同对象的 hashCode 方法返回值确实是不一致的(实现原理大致就是将该对象的内存地址做一些处理后返回),但是这一点在《Java 编程规范》中并未做强制要求;

    然后再说 equals 方法:

    /**
         * Indicates whether some other object is "equal to" this one.
         * <p>
         * The {@code equals} method implements an equivalence relation
         * on non-null object references:
         * <ul>
         * <li>It is <i>reflexive</i>: for any non-null reference value
         *     {@code x}, {@code x.equals(x)} should return
         *     {@code true}.
         * <li>It is <i>symmetric</i>: 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}.
         * <li>It is <i>transitive</i>: 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}.
         * <li>It is <i>consistent</i>: 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.
         * <li>For any non-null reference value {@code x},
         *     {@code x.equals(null)} should return {@code false}.
         * </ul>
         * <p>
         * 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}).
         * <p>
         * 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.
         *
         * @param   obj   the reference object with which to compare.
         * @return  {@code true} if this object is the same as the obj
         *          argument; {@code false} otherwise.
         * @see     #hashCode()
         * @see     java.util.HashMap
         */
        public boolean equals(Object obj) {
            return (this == obj);
        }
    

    可以看到该方法的实现是用双等号做判等校验的,这样其实就是比较两个对象的内存地址。该方法有一些特性:

    1. 自反省
    2. 对象性
    3. 传递性
    4. 一致性

    熟悉的感觉,好像那个高中数学公理也有这样的特性。
    该方法的参数可以是 null,由此看见:在 Java 中 null 虽非对象,却是可以作为对象实例的值;
    还有一点要注意:覆写 equals 方法后要记得覆写 hashCode 方法,以维持 hashCode 方法的第二个约定:如果两个对象通过 equals 方法判等时结果返回真,那么这两个对象调用 hashCode 方法的返回值应该一致;

    Double Kill

    熟悉了上面的 hashCode 方法和 equals 方法的作用,那么再看 toString 方法就易如反掌了:

    /**
         * Returns a string representation of the object. In general, the
         * {@code toString} method returns a string that
         * "textually represents" this object. The result should
         * be a concise but informative representation that is easy for a
         * person to read.
         * It is recommended that all subclasses override this method.
         * <p>
         * The {@code toString} method for class {@code Object}
         * returns a string consisting of the name of the class of which the
         * object is an instance, the at-sign character `{@code @}', and
         * the unsigned hexadecimal representation of the hash code of the
         * object. In other words, this method returns a string equal to the
         * value of:
         * <blockquote>
         * <pre>
         * getClass().getName() + '@' + Integer.toHexString(hashCode())
         * </pre></blockquote>
         *
         * @return  a string representation of the object.
         */
        public String toString() {
            return getClass().getName() + "@" + Integer.toHexString(hashCode());
        }
    

    为了人类的可读性,toString 方法把 hashCode 方法返回的整数类型转换为了十六进制字符串类型。

    参考

    1. https://www.cnblogs.com/ttylinux/p/6539436.html
  • 相关阅读:
    敏捷开发流程的8个步骤
    PingCode Wiki ——国内最顶级的产研团队知识库产品介绍
    国内外最知名的9大工作任务管理软件盘点
    国内外最好用的18个协同办公系统盘点
    知识库的作用
    国内外好用的OKR管理工具有哪些?
    敏捷宣言及完整解读
    如何在敏捷中管理和减少技术负债?
    敏捷开发框架都有哪些
    PingCode与Jira 敏捷开发管理能力的对比
  • 原文地址:https://www.cnblogs.com/optor/p/8461616.html
Copyright © 2020-2023  润新知