Java的Object对象

Object对象是除了基础对象之外,所有的对象都需要继承的父对象,包括数组也继承了Object

Object里面的关键函数罗列如下:

clone();调用该函数需要实现 Cloneable,否则会抛出  CloneNotSupportedException的异常。

equals();用来判断两个对象是否相等的函数,默认的是两个对象的地址比较,在使用Compare计算的时候,往往需要重写这个函数。

finalize();这个函数在对象被消解的时候,例如垃圾回收的时候等,会被调用,如果对象使用了不可被自动回收的内存空间等资源,应该在这个函数里面收回。

hashCode();返回的是这个对象的hash值,期内部的实现代码如下:

        int lockWord = shadow$_monitor_;
        final int lockWordMask = 0xC0000000;  // Top 2 bits.
        final int lockWordStateHash = 0x80000000;  // Top 2 bits are value 2 (kStateHash).
        if ((lockWord & lockWordMask) == lockWordStateHash) {
            return lockWord & ~lockWordMask;
        }
        return System.identityHashCode(this);
& lockWordMask是获取最高两位,
lockWordStateHash是指最高两位是2(10),最高位是符号位,但是不明白为什么要获取两位。
return lockWord & ~lockWordMask; ~是非运算符,所以这句话是返回了除了最高两位的所有其它位的值。

如果不满足上述条件,返回的是
System.identityHashCode(this);,这个是native的方法,没有深入

notify():唤醒被这个对象的monitor标记等待的线程,如果线程的数量大于1,那么被唤醒的线程是由VM自行决定的。注意被唤醒的线程不一定立即执行,至少要等待当前调用notify的线程释放这个对象的monitor,或者等待其他正好同步锁定该对象的线程释放了该对象。 当然了,也不是任何地方都可以调用notify的,调用的地方必须持有对象的monitor,可以有以下几种情况:1.在一个同步( synchronized)方法中;2.在一段该对象的同步代码块中;3.如果这个变量是类变量(static),同步的静态方法也持有。

notifyAll(): 与上面所属的notify类似,只不过是唤醒了所有的线程,当然这些线程也不是立即执行,理由同上。

toString():这个对象的字符串描述,默认的是返回类名和实例的hashCode,代码如下:

    public String toString() {
        return getClass().getName() + ‘@‘ + Integer.toHexString(hashCode());
    }

wait(): 通知当前线程挂起,当对象的notify或者notifyAll被调用的时候才会被重新唤醒,wait了的thread是可以被中断(interrupt)的。当线程wait的时候,这个线程其实丢失了对象的monitor,当被notify的时候,会在程序执行前重新请求到对象的monitor。

还有两个wait函数是带参数的,参数指明了线程的wait时长,如果在这个时长内,线程没有被唤醒,那么当时间到达的时候,这个线程也会被重新唤醒。其他的与上面的wait一致,对了时间为0,说明没有超时时间,时间不可以小于零,否则抛出 IllegalArgumentException

下文中的shadow$_monitor_和shadow$_klass_ 是Android sdk21之后Object增加的两个字段。前者好像是用来表明地址的,后者是用来说明类型的。

Android中的Object源码如下:
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package java.lang;

/**
 * The root class of the Java class hierarchy. All non-primitive types
 * (including arrays) inherit either directly or indirectly from this class.
 *
 * <a name="writing_equals"><h4>Writing a correct {@code equals} method</h4></a>
 * <p>Follow this style to write a canonical {@code equals} method:
 * <pre>
 *   // Use @Override to avoid accidental overloading.
 *   @Override public boolean equals(Object o) {
 *     // Return true if the objects are identical.
 *     // (This is just an optimization, not required for correctness.)
 *     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.
 *     if (!(o instanceof MyType)) {
 *       return false;
 *     }
 *
 *     // Cast to the appropriate type.
 *     // This will succeed because of the instanceof, and lets us access private fields.
 *     MyType lhs = (MyType) o;
 *
 *     // Check each field. Primitive fields, reference fields, and nullable reference
 *     // fields are all treated differently.
 *     return primitiveField == lhs.primitiveField &amp;&amp;
 *             referenceField.equals(lhs.referenceField) &amp;&amp;
 *             (nullableField == null ? lhs.nullableField == null
 *                                    : nullableField.equals(lhs.nullableField));
 *   }
 * </pre>
 * <p>If you override {@code equals}, you should also override {@code hashCode}: equal
 * instances must have equal hash codes.
 *
 * <p>See <i>Effective Java</i> item 8 for much more detail and clarification.
 *
 * <a name="writing_hashCode"><h4>Writing a correct {@code hashCode} method</h4></a>
 * <p>Follow this style to write a canonical {@code hashCode} method:
 * <pre>
 *   @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;
 *   }
 * </pre>
 *
 * <p>If you don‘t intend your type to be used as a hash key, don‘t simply rely on the default
 * {@code hashCode} implementation, because that silently and non-obviously breaks any future
 * code that does use your type as a hash key. You should throw instead:
 * <pre>
 *   @Override public int hashCode() {
 *     throw new UnsupportedOperationException();
 *   }
 * </pre>
 *
 * <p>See <i>Effective Java</i> item 9 for much more detail and clarification.
 *
 * <a name="writing_toString"><h4>Writing a useful {@code toString} method</h4></a>
 * <p>For debugging convenience, it‘s common to override {@code toString} in this style:
 * <pre>
 *   @Override public String toString() {
 *     return getClass().getName() + "[" +
 *         "primitiveField=" + primitiveField + ", " +
 *         "referenceField=" + referenceField + ", " +
 *         "arrayField=" + Arrays.toString(arrayField) + "]";
 *   }
 * </pre>
 * <p>The set of fields to include is generally the same as those that would be tested
 * in your {@code equals} implementation.
 * <p>See <i>Effective Java</i> item 10 for much more detail and clarification.
 */
public class Object {

    private transient Class<?> shadow$_klass_;
    private transient int shadow$_monitor_;

    // Uncomment the following two fields to enable brooks pointers.
    // Meant to do "#ifdef USE_BROOKS_POINTER ... #endif" but no macros.
    //
    // Note names use a ‘x‘ prefix and the _x_rb_ptr_ field is of
    // type int instead of Object to go with the alphabetical/by-type
    // field order.
    // private transient int shadow$_x_rb_ptr_;
    // private transient int shadow$_x_xpadding_;

    /**
     * Constructs a new instance of {@code Object}.
     */
    public Object() {
    }

    /**
     * Creates and returns a copy of this {@code Object}. The default
     * implementation returns a so-called "shallow" copy: It creates a new
     * instance of the same class and then copies the field values (including
     * object references) from this instance to the new instance. A "deep" copy,
     * in contrast, would also recursively clone nested objects. A subclass that
     * needs to implement this kind of cloning should call {@code super.clone()}
     * to create the new instance and then create deep copies of the nested,
     * mutable objects.
     *
     * @return a copy of this object.
     * @throws CloneNotSupportedException
     *             if this object‘s class does not implement the {@code
     *             Cloneable} interface.
     */
    protected Object clone() throws CloneNotSupportedException {
        if (!(this instanceof Cloneable)) {
            throw new CloneNotSupportedException("Class " + getClass().getName() +
                                                 " doesn‘t implement Cloneable");
        }

        return internalClone();
    }

    /*
     * Native helper method for cloning.
     */
    private native Object internalClone();

    /**
     * Compares this instance with the specified object and indicates if they
     * are equal. In order to be equal, {@code o} must represent the same object
     * as this instance using a class-specific comparison. The general contract
     * is that this comparison should be reflexive, symmetric, and transitive.
     * Also, no object reference other than null is equal to null.
     *
     * <p>The default implementation returns {@code true} only if {@code this ==
     * o}. See <a href="{@docRoot}reference/java/lang/Object.html#writing_equals">Writing a correct
     * {@code equals} method</a>
     * if you intend implementing your own {@code equals} method.
     *
     * <p>The general contract for the {@code equals} and {@link
     * #hashCode()} methods is that if {@code equals} returns {@code true} for
     * any two objects, then {@code hashCode()} must return the same value for
     * these objects. This means that subclasses of {@code Object} usually
     * override either both methods or neither of them.
     *
     * @param o
     *            the object to compare this instance with.
     * @return {@code true} if the specified object is equal to this {@code
     *         Object}; {@code false} otherwise.
     * @see #hashCode
     */
    public boolean equals(Object o) {
        return this == o;
    }

    /**
     * Invoked when the garbage collector has detected that this instance is no longer reachable.
     * The default implementation does nothing, but this method can be overridden to free resources.
     *
     * <p>Note that objects that override {@code finalize} are significantly more expensive than
     * objects that don‘t. Finalizers may be run a long time after the object is no longer
     * reachable, depending on memory pressure, so it‘s a bad idea to rely on them for cleanup.
     * Note also that finalizers are run on a single VM-wide finalizer thread,
     * so doing blocking work in a finalizer is a bad idea. A finalizer is usually only necessary
     * for a class that has a native peer and needs to call a native method to destroy that peer.
     * Even then, it‘s better to provide an explicit {@code close} method (and implement
     * {@link java.io.Closeable}), and insist that callers manually dispose of instances. This
     * works well for something like files, but less well for something like a {@code BigInteger}
     * where typical calling code would have to deal with lots of temporaries. Unfortunately,
     * code that creates lots of temporaries is the worst kind of code from the point of view of
     * the single finalizer thread.
     *
     * <p>If you <i>must</i> use finalizers, consider at least providing your own
     * {@link java.lang.ref.ReferenceQueue} and having your own thread process that queue.
     *
     * <p>Unlike constructors, finalizers are not automatically chained. You are responsible for
     * calling {@code super.finalize()} yourself.
     *
     * <p>Uncaught exceptions thrown by finalizers are ignored and do not terminate the finalizer
     * thread.
     *
     * See <i>Effective Java</i> Item 7, "Avoid finalizers" for more.
     */
    @FindBugsSuppressWarnings("FI_EMPTY")
    protected void finalize() throws Throwable {
    }

    /**
     * Returns the unique instance of {@link Class} that represents this
     * object‘s class. Note that {@code getClass()} is a special case in that it
     * actually returns {@code Class<? extends Foo>} where {@code Foo} is the
     * erasure of the type of the expression {@code getClass()} was called upon.
     * <p>
     * As an example, the following code actually compiles, although one might
     * think it shouldn‘t:
     * <p>
     * <pre>{@code
     *   List<Integer> l = new ArrayList<Integer>();
     *   Class<? extends List> c = l.getClass();}</pre>
     *
     * @return this object‘s {@code Class} instance.
     */
    public final Class<?> getClass() {
      return shadow$_klass_;
    }

    /**
     * Returns an integer hash code for this object. By contract, any two
     * objects for which {@link #equals} returns {@code true} must return
     * the same hash code value. This means that subclasses of {@code Object}
     * usually override both methods or neither method.
     *
     * <p>Note that hash values must not change over time unless information used in equals
     * comparisons also changes.
     *
     * <p>See <a href="{@docRoot}reference/java/lang/Object.html#writing_hashCode">Writing a correct
     * {@code hashCode} method</a>
     * if you intend implementing your own {@code hashCode} method.
     *
     * @return this object‘s hash code.
     * @see #equals
     */
    public int hashCode() {
        int lockWord = shadow$_monitor_;
        final int lockWordMask = 0xC0000000;  // Top 2 bits.
        final int lockWordStateHash = 0x80000000;  // Top 2 bits are value 2 (kStateHash).
        if ((lockWord & lockWordMask) == lockWordStateHash) {
            return lockWord & ~lockWordMask;
        }
        return System.identityHashCode(this);
    }

    /**
     * Causes a thread which is waiting on this object‘s monitor (by means of
     * calling one of the {@code wait()} methods) to be woken up. If more than
     * one thread is waiting, one of them is chosen at the discretion of the
     * VM. The chosen thread will not run immediately. The thread
     * that called {@code notify()} has to release the object‘s monitor first.
     * Also, the chosen thread still has to compete against other threads that
     * try to synchronize on the same object.
     *
     * <p>This method can only be invoked by a thread which owns this object‘s
     * monitor. A thread becomes owner of an object‘s monitor
     * <ul>
     * <li>by executing a synchronized method of that object;</li>
     * <li>by executing the body of a {@code synchronized} statement that
     * synchronizes on the object;</li>
     * <li>by executing a synchronized static method if the object is of type
     * {@code Class}.</li>
     * </ul>
     *
     * @see #notifyAll
     * @see #wait()
     * @see #wait(long)
     * @see #wait(long,int)
     * @see java.lang.Thread
     */
    public final native void notify();

    /**
     * Causes all threads which are waiting on this object‘s monitor (by means
     * of calling one of the {@code wait()} methods) to be woken up. The threads
     * will not run immediately. The thread that called {@code notify()} has to
     * release the object‘s monitor first. Also, the threads still have to
     * compete against other threads that try to synchronize on the same object.
     *
     * <p>This method can only be invoked by a thread which owns this object‘s
     * monitor. A thread becomes owner of an object‘s monitor
     * <ul>
     * <li>by executing a synchronized method of that object;</li>
     * <li>by executing the body of a {@code synchronized} statement that
     * synchronizes on the object;</li>
     * <li>by executing a synchronized static method if the object is of type
     * {@code Class}.</li>
     * </ul>
     *
     * @throws IllegalMonitorStateException
     *             if the thread calling this method is not the owner of this
     *             object‘s monitor.
     * @see #notify
     * @see #wait()
     * @see #wait(long)
     * @see #wait(long,int)
     * @see java.lang.Thread
     */
    public final native void notifyAll();

    /**
     * Returns a string containing a concise, human-readable description of this
     * object. Subclasses are encouraged to override this method and provide an
     * implementation that takes into account the object‘s type and data. The
     * default implementation is equivalent to the following expression:
     * <pre>
     *   getClass().getName() + ‘@‘ + Integer.toHexString(hashCode())</pre>
     * <p>See <a href="{@docRoot}reference/java/lang/Object.html#writing_toString">Writing a useful
     * {@code toString} method</a>
     * if you intend implementing your own {@code toString} method.
     *
     * @return a printable representation of this object.
     */
    public String toString() {
        return getClass().getName() + ‘@‘ + Integer.toHexString(hashCode());
    }

    /**
     * Causes the calling thread to wait until another thread calls the {@code
     * notify()} or {@code notifyAll()} method of this object. This method can
     * only be invoked by a thread which owns this object‘s monitor; see
     * {@link #notify()} on how a thread can become the owner of a monitor.
     *
     * <p>A waiting thread can be sent {@code interrupt()} to cause it to
     * prematurely stop waiting, so {@code wait} should be called in a loop to
     * check that the condition that has been waited for has been met before
     * continuing.
     *
     * <p>While the thread waits, it gives up ownership of this object‘s
     * monitor. When it is notified (or interrupted), it re-acquires the monitor
     * before it starts running.
     *
     * @throws IllegalMonitorStateException
     *             if the thread calling this method is not the owner of this
     *             object‘s monitor.
     * @throws InterruptedException if the current thread has been interrupted.
     *             The interrupted status of the current thread will be cleared before the exception
     *             is thrown.
     * @see #notify
     * @see #notifyAll
     * @see #wait(long)
     * @see #wait(long,int)
     * @see java.lang.Thread
     */
    public final native void wait() throws InterruptedException;

    /**
     * Causes the calling thread to wait until another thread calls the {@code
     * notify()} or {@code notifyAll()} method of this object or until the
     * specified timeout expires. This method can only be invoked by a thread
     * which owns this object‘s monitor; see {@link #notify()} on how a thread
     * can become the owner of a monitor.
     *
     * <p>A waiting thread can be sent {@code interrupt()} to cause it to
     * prematurely stop waiting, so {@code wait} should be called in a loop to
     * check that the condition that has been waited for has been met before
     * continuing.
     *
     * <p>While the thread waits, it gives up ownership of this object‘s
     * monitor. When it is notified (or interrupted), it re-acquires the monitor
     * before it starts running.
     *
     * <p>A timeout of zero means the calling thread should wait forever unless interrupted or
     * notified.
     *
     * @param millis
     *            the maximum time to wait in milliseconds.
     * @throws IllegalArgumentException
     *             if {@code millis < 0}.
     * @throws IllegalMonitorStateException
     *             if the thread calling this method is not the owner of this
     *             object‘s monitor.
     * @throws InterruptedException if the current thread has been interrupted.
     *             The interrupted status of the current thread will be cleared before the exception
     *             is thrown.
     * @see #notify
     * @see #notifyAll
     * @see #wait()
     * @see #wait(long,int)
     * @see java.lang.Thread
     */
    public final void wait(long millis) throws InterruptedException {
        wait(millis, 0);
    }

    /**
     * Causes the calling thread to wait until another thread calls the {@code
     * notify()} or {@code notifyAll()} method of this object or until the
     * specified timeout expires. This method can only be invoked by a thread
     * that owns this object‘s monitor; see {@link #notify()} on how a thread
     * can become the owner of a monitor.
     *
     * <p>A waiting thread can be sent {@code interrupt()} to cause it to
     * prematurely stop waiting, so {@code wait} should be called in a loop to
     * check that the condition that has been waited for has been met before
     * continuing.
     *
     * <p>While the thread waits, it gives up ownership of this object‘s
     * monitor. When it is notified (or interrupted), it re-acquires the monitor
     * before it starts running.
     *
     * <p>A timeout of zero means the calling thread should wait forever unless interrupted or
     * notified.
     *
     * @param millis
     *            the maximum time to wait in milliseconds.
     * @param nanos
     *            the fraction of a millisecond to wait, specified in
     *            nanoseconds.
     * @throws IllegalArgumentException
     *             if {@code millis < 0}, {@code nanos < 0} or {@code nanos >
     *             999999}.
     * @throws IllegalMonitorStateException
     *             if the thread calling this method is not the owner of this
     *             object‘s monitor.
     * @throws InterruptedException if the current thread has been interrupted.
     *             The interrupted status of the current thread will be cleared before the exception
     *             is thrown.
     * @see #notify
     * @see #notifyAll
     * @see #wait()
     * @see #wait(long,int)
     * @see java.lang.Thread
     */
    public final native void wait(long millis, int nanos) throws InterruptedException;
}
时间: 2024-10-15 20:42:36

Java的Object对象的相关文章

java 数组的 toString 方法和 equals 方法以及 java.lang.Object 对象的 toString 方法和 equals 方法

1 public class Test { 2 public static void main(String[] args) { 3 int[] a = {1, 2, 4, 6}; 4 int[] b = a; 5 int[] c = {1, 2, 4, 6}; 6 7 //下面这个方法打印的是a数组的引用地址 8 System.out.println(a.toString()); 9 //下面这个方法比较的是两个数组的引用是否相等 10 System.out.println("a.equals

Java之Object对象中的wait()和notifyAll()用法

用一个例子来说明Object对象中的wait方法和notifyAll方法的使用. 首先定义一个消息类,用于封装数据,以供读写线程进行操作: 1 /** 2 * 消息 3 * 4 * @author syj 5 */ 6 public class Message { 7 8 private String msg; 9 10 public String getMsg() { 11 return msg; 12 } 13 14 public void setMsg(String msg) { 15 t

Java中Object对象有哪些方法

一,所有方法 1. getClass() 2. hashCode()3. equals()4. toString()5. clone()6. wait()...7. notify()8. notifyAll()9. finalize() 二,每个方法详解 protected Object clone()创建并返回此对象的一个副本.boolean equals(Object obj)指示其他某个对象是否与此对象“相等”.protected void finalize()当垃圾回收器确定不存在对该对

Java语言中Object对象的hashCode()取值的底层算法是怎样实现的?

Java语言中,Object对象有个特殊的方法:hashcode(), hashcode()表示的是JVM虚拟机为这个Object对象分配的一个int类型的数值,JVM会使用对象的hashcode值来提高对HashMap.Hashtable哈希表存取对象的使用效率. 关于Object对象的hashCode()返回值,网上对它就是一个简单的描述:"JVM根据某种策略生成的",那么这种策略到底是什么呢?我有一个毛病,遇到这种含糊其辞的东西,就想探个究竟,所以,本文就将hashCode()本

java学习中,object 对象的使用(toString、equals、hashCode)(java 学习中的小记录)

java学习中,object 对象的使用(java 学习中的小记录)作者:王可利(Star·星星) object 对象(参考API学习) 重点掌握三个方法: 1.toString 返回该对象的字符串表示. 2.equals(object obj)指示其他某个对象是否与这个对象相等. 3.hashCode() 返回对象的哈希码. 详见代码的注释分析(一个是Person类重写方法,一个是Star类使用方法) Star类代码: 1 package study; 2 3 public class sta

Java Object 对象创建的方式 [ 转载 ]

Java Object 对象创建的方式 [ 转载 ] @author http://blog.csdn.net/mhmyqn/article/details/7943411 显式创建 有4种显式地创建对象的方式: 1.构造器:用new语句创建对象,这是最常用的创建对象的方式. 2.反射:运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法. 3.克隆:调用对象的clone()方法. 4.序列化:运用反

Java Object 对象序列化和反序列化

Java Object 对象序列化和反序列化 @author ixenos 对象序列化是什么 1.对象序列化就是把一个对象的状态转化成一个字节流. 我们可以把这样的字节流存储为一个文件,作为对这个对象的复制(深拷贝):在一些分布式应用中,我们还可以把对象的字节流发送到网络上的其他计算机. 反序列化是把流结构的对象恢复为其原有形式 2.Java平台允许我们在内存中创建可复用的Java对象,但一般情况下,只有当JVM处于运行时,这些对象才可能存在,即,这些对象的生命周期不会比JVM的生命周期更长.但

Java Object 对象上的wait(),notify(),notifyAll()方法理解

第一阶段理解(2017-7-27): Java 将wait(),notify(),notifyAll()方法放在Object对象上,也就是说任何一个对象都可以调用这个方法,这与”任何一个对象都有一个内置锁,可以用于线程同步“是照应的.因此,当某个线程要释放cpu争夺权,让自己进入等待状态时,调用 某个锁(对象)上的wait()方法,也就是让当前线程等待其它线程调用该锁上的notify()或notify()方法.线程间通过同步锁来实现等待与唤醒协作.简单例子: 1 package com.lyyc

java.lang.Object.hashCode()的返回值到底是不是对象内存地址?

刚学Java的时候我也有过这种怀疑,但一直没有验证:最近在OSCHINA上看到有人在回答问题时也这么说,于是萌生了一探究竟的想法--java.lang.Object.hashCode()的返回值到底是不是对象内存地址? (顺带回顾一下JNI) hashCode契约 说到这个问题,大家的第一反应一定和我一样--去查Object.hashCode的源码,但翻开源码,看到的却是这样的(Oracle JDK 8): /** * Returns a hash code value for the obje