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
posted @ 2018-02-23 13:30  optor  阅读(230)  评论(0编辑  收藏  举报