/*
* Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
* 版权所有(c) 1994年,2012年,甲骨文和/或其附属公司。保留所有权利。ORACLE专有/保密。使用受许可条款约束。
*/
package java.lang;
/**
* 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.
* 类{@code Object}是类层次结构的根。每个类都有一个超类{@code Object}。所有对象,包括数组,实现这个类的方法
* @author unascribed
* @see java.lang.Class
* @since JDK1.0
*/
public class Object {
什么鬼?哈哈哈,我刚看到这方法,一脸懵逼。 从名字上理解,这个方法是注册native方法(本地方法,由JVM实现,底层是C/C++实现的) 向谁注册呢?当然是向JVM ,当有程序调用到native方法时,JVM才好去找到这些底层的方法进行调用。
Object中的native方法,并使用registerNatives()向JVM进行注册。
private static native void registerNatives();
static {
registerNatives();
}
为什么要使用静态方法,还要放到静态块中呢?
我们知道了在类初始化的时候,会依次从父类到本类的类变量及类初始化块中的类变量及方法按照定义顺序放到< clinit>方法中,这样可以保证父类的类变量及方法的初 始化一定先于子类。 所以当子类调用相应native方法,比如计算hashCode时,一定可以保证能够调用到JVM的native方法。
static JNINativeMethod methods[] = {
{
"hashCode", "()I", (void *)&JVM_IHashCode},
{
"wait", "(J)V", (void *)&JVM_MonitorWait},
{
"notify", "()V", (void *)&JVM_MonitorNotify},
{
"notifyAll", "()V", (void *)&JVM_MonitorNotifyAll},
{
"clone", "()Ljava/lang/Object;", (void *)&JVM_Clone},
};
/**
* Returns the runtime class of this {@code Object}. The returned
* {@code Class} object is the object that is locked by {@code
* static synchronized} methods of the represented class.
* 返回运行时类{@code Object}。返回的{@code Class}对象是被当前类的方法锁定的类(因为有静态同步的注解代码)。
* <p><b>The actual result type is {@code Class<? extends |X|>}
* where {@code |X|} is the erasure of the static type of the
* expression on which {@code getClass} is called.</b> For
* example, no cast is required in this code fragment:</p>
* 动物类就是动物类,狗类可以说是狗类,也可以说是动物类,但是动物类不能强制转换为狗类。例如,在这个代码片段中不需要强制转换:
* <p>
* {@code Number n = 0; }<br>
* {@code Class<? extends Number> c = n.getClass(); }
* </p>
*
* @return The {@code Class} object that represents the runtime
* class of this object.
* @jls 15.8.2 Class Literals
*/
这是一个public的方法,我们可以直接通过对象调用。
类加载的第一阶段类的加载就是将.class文件加载到内存,并生成一个java.lang.Class对象的过程。getClass()方法就是获取这个对象,这是当前类的对象在运行 时类的所有信息的集合。这个方法是反射三种方式之一。
反射三种方式:
对象的getClass();
类名.class;
Class.forName();
package com.bjsxt.clazz;
import java.lang.reflect.Method;
/**
* Description:
* Author: taimi 37310
* Version: 1.0
* Create Date Time: 2022/1/28 15:56.
* Update Date Time:
*
* @see
*/
public class a extends ObjectTest {
private void privateTest(String str) {
System.out.println(str);
}
public void say(String str) {
System.out.println(str);
}
}
class ObjectTest {
public static void main(String[] args) throws Exception {
ObjectTest O = new a();
//获取对象运行的Class对象
Class<? extends ObjectTest> aClass = O.getClass();
System.out.println(aClass);
//getDeclaredMethod这个方法可以获取所有的方法,包括私有方法
Method privateTest = aClass.getDeclaredMethod("privateTest", String.class);
//privateTest.invoke(aClass.newInstance(),"HELLO");//Class com
// .bjsxt.clazz.ObjectTest can not access a member of class com.bjsxt.clazz.a with modifiers //"private"
//取消java访问修饰符限制。
privateTest.setAccessible(true);
privateTest.invoke(aClass.newInstance(), "private method test");
privateTest.invoke(aClass.newInstance(),"HELLO");
//getMethod只能获取public方法
Method say = aClass.getMethod("say", String.class);
say.invoke(aClass.newInstance(), "Hello World");
}
}
//输出结果:
//class com.bjsxt.clazz.a
//private method test
//HELLO
// Hello World
反射主要用来获取运行时的信息,可以将java这种静态语言动态化,可以在编写代码时将一个子对象赋值给父类的一个引用,在运行时通过反射可以或许运行时对象的所有信息,即多态的体现。对于反射知识还是很多的,这里就不展开讲了。
public final native Class<?> getClass();
/**
* 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}.
*返回对象的hash值,这个方法体现hash表的好处,和java.util.HashMap提供的差不多!
* <p>
* The general contract of {@code hashCode} is:
*hashCode大体合同如下:
* <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,
* 在一个java应用一次执行中相同对象不管什么时候被调用多少次,这个方法要返回相同的整数。
*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.
* 一个应用中不同执行中hashcode不需要保持一致!
* <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.
*如果根据{@code equals(Object)}equals相同,{@code hashCode}也一定相同!!!
* <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.
* 如果两个对象的equals不相同,hashcode不需要一定不一样,也即是说可以相同!
*However, the
* programmer should be aware that producing distinct integer results
* for unequal objects may improve the performance of hash tables.
*我们一定要知道,不同对象产生不同hashcode可以提高hash表的性能!!!
* </ul>
* <p>
* As much as is reasonably practical, the hashCode method defined by
* class {@code Object} does return distinct integers for distinct
* objects.
*在合理的情况下,该方法会为不同的对象提供不同的hashcode值!!!
(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.)
*该值是内部地址的转换,不需要通过java编程语言!!!
*
* @return a hash code value for this object.
* @see java.lang.Object#equals(java.lang.Object)
* @see java.lang.System#identityHashCode
*/
这是一个public的方法,所以 子类可以重写 它。这个方法返回当前对象的hashCode值,这个值是一个整数范围内的(-2^31 ~ 2^31 - 1)数字。
对于hashCode有以下几点约束
在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改;
如果两个对象 x.equals(y) 方法返回true,则x、y这两个对象的hashCode必须相等。
如果两个对象x.equals(y) 方法返回false,则x、y这两个对象的hashCode可以相等也可以不等。 但是,为不相等的对象生成不同整数结果可以提高哈希表的性能。
默认的hashCode是将内存地址转换为的hash值,重写过后就是自定义的计算方式;也可以通过System.identityHashCode(Object)来返回原本的hashCode。
public class HashCodeTest {
private int age;
private String name;
@Override
public int hashCode() {
Object[] a = Stream.of(age, name).toArray();
int result = 1;
for (Object element : a) {
result = 31 * result + (element == null ? 0 : element.hashCode());
}
return result;
}
}
推荐使用Objects.hash(Object… values)方法。相信看源码的时候,都看到计算hashCode都使用了31作为基础乘数, 为什么使用31呢?我比较赞同与理解result
Object源代码翻译分析
最新推荐文章于 2024-07-27 13:31:57 发布
![](https://img-home.csdnimg.cn/images/20240711042549.png)