你真的了解Object源码吗
欢迎点赞阅读,一同学习交流,有疑问请留言 。
GitHub上也有开源 JavaHouse 欢迎star
引入
Object 应该是比较简单的源码了。现在我们来分析一下他。Object 是类层次结构的根。Java体系里面的每个类默认都有一个超类就是 Object。总之,所有对象,包含数组,都默认实现该类的方法。
native 关键字
因为 Object 类里面有很多地方都用到 native 关键字。我们先了解一下这家伙。native 关键字是 JNI(Java Native Interface)的重要体现。什么是 JNI ,JNI 是Java调用其他语言(c,c++) 的一种机制。native 关键字修饰的是方法,起声明作用,告诉 JVM 老哥自己去调用这个方法。 这个方法的实现在别的语言那里已经实现,我们是看不到源码的。
初始化
private static native void registerNatives();
static {
registerNatives();
}
源码里面一个静态块,一个静态方法和一个没有显示的默认构造方法,没有成员变量。可以看出来 registerNatives() 方法只会被调用一次。
getClass() 方法
public final native Class<?> getClass();
getClass()方法被native修饰,告诉 JVM 自己去调用。同时被 final 修饰,所以不能被子类重写。主要作用是返回正在运行的类别(Class)。
hashCode() 方法
public native int hashCode();
getClass()方法被native修饰,告诉 JVM 自己去调用,可以被重写。同时被 final 修饰,所以不能被子类重写。该方法主要是返回对象的hashcode,主要是为了一些哈希表的数据结构服务的,比如 HashMap 。
在 Java 中hancode 与 对象是否相等密切相关。 如果两个对象相等,则 hashcode 一定相等,但是 hashcode 相等,两个对象不一定相等。如果 hashcode 不相等,那么这两个对象一定不相等。
equals(Object obj)
public boolean equals(Object obj) {
return (this == obj);
}
该方法可以被重写,主要用来判断两个对象是否相等。
该方法有一些约定。
- 对象任意一个非空对象x, x.equals(x) 返回 true。
- 对象任意两个非空对象 x,y,如果 x.equals(y) 返回true,那么 y.equals(x) 也会返回true, 具有对称性。
- 对象任意三个非空对象 x,y,z,如果 x.equals(y) 返回true, y.equals(z) 返回true, 那么x.equals(z) 返回true, 具有传递性。
- 对象任意两个非空对象 x,y,在什么发生变化的情况写,x.equals(y) 返回总是 true 或者 flase,具有一直性。
- 对象任意一个非空对象x, x.equals(null) 返回 false。
Object#equals(Object obj)方法,比较的是内存地址,通常实际应用中我们想比较的是两个对象里面的属性内容是否相等,所以会重写该方法。这里要注意重写 equals(Object obj) 的时候,也要重写 hashCode() 方法。 因为 Java 规定:如果两个对象相等,那么他们的 hashcode 也要相等。举个 Integer 的例子:
@Override
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
@Override
public int hashCode() {
return Integer.hashCode(value);
}
public static int hashCode(int value) {
return value;
}
clone()
protected native Object clone() throws CloneNotSupportedException;
该方法被native修饰,告诉 JVM 自己去调用。当我们在自定义类中使用该方法的时候,需要继承一个 Cloneable 接口,否则会抛出无法克隆的异常。该方法是一个浅复制,不是深复制。
浅拷贝:对基本数据类型进行值传递,对引用数据类型进行引用传递般的拷贝,此为浅拷贝。
深拷贝:对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容,此为深拷贝。
- 使用代码
@Data
public class Person extends Man implements Cloneable {
private String name;
private Person person;
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
person.setName("chen");
Person clone = (Person)person.clone();
System.out.println(clone.toString());
System.out.println("person.equals(clone):"+person.equals(clone));
System.out.println("person == clone:"+(person == clone));
System.out.println("person.person == clone.person:"+(person.person == clone.person));
}
- 结果
Person(name=chen, person=null)
person.equals(clone):true
person == clone:false
person.person == clone.person:true
notify()、notifyAll() 和 wait()
public final native void notify();
public final native void notifyAll();
public final void wait() throws InterruptedException {
wait(0);
}
notify() 随机唤醒一个等待线程,notifyAll() 唤醒全部的等待线程。wait() 方法让当前线程进入等待状态。

无论当前线程调用哪个方法,都有一个前提:当前线程拥有对象的监视器。实现方法也很简单,配合 synchronized 关键字使用。
- 实现方法
synchronized (obj) {
while (true)
obj.wait();
// obj.notify();
}
举一个实际的例子
- 多线程打印奇偶数
public static void main(String[] args) {
Thread thread = new Thread(() -> {
for ( int i = 0; i < 100; i += 2) {
synchronized (a) {
System.out.println(Thread.currentThread().getName()+":"+i);
try {
a.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
Thread thread1 = new Thread(() -> {
for (int i = 1; i < 100; i += 2) {
synchronized (a) {
System.out.println(Thread.currentThread().getName()+":"+i);
a.notify();
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread.start();thread1.start();
}
finalize()
protected void finalize() throws Throwable { }
当垃圾回收器确定不再有对该对象的引用时,由垃圾回收器在对象上调用该方法。该方法只会被调用一次。
参考
如果我的文章帮助到您,可以关注我的微信公众号,第一时间分享文章给您

你真的了解Object源码吗的更多相关文章
- jdk之object源码理解
Java所有类都继承与Object,本文谈谈我对object源码的理解,如果有错的,请看官多多批评指正. 1.registerNatives() private static native void ...
- Object 源码阅读
Object 源码阅读 /** * Object 类是类继承结构的根类,每一个类型都以 Object 作为其父类,包括数组. */ public class Object { private stat ...
- Object源码
1.Object是所有类的父类,默认会继承Object. 2.Object类中常用的方法有:getClass().hashCode().equals().clone().toString().fina ...
- Object源码分析(二)
第五个方法:protected native Object clone() throws CloneNotSupportedException; 源码简介: clone方法首先会判对象是否实现了Clo ...
- Object源码分析(一)
刚注册博客,准备学习一下java源码,当然首先从Object看起. 介绍一下Object: Object是所有类层次结构的根,所有的类都将Object作为超类.所有的对象,包括数组,都实现了Objec ...
- JDK源码阅读(一):Object源码分析
最近经过某大佬的建议准备阅读一下JDK的源码来提升一下自己 所以开始写JDK源码分析的文章 阅读JDK版本为1.8 目录 Object结构图 构造器 equals 方法 getClass 方法 has ...
- java中Object源码理解
java阅读笔记 1.object getClass() 返回是的此object运行时的类,返回的对象是被object锁定的对象,调用这个方法不需要进行强转 public static void ma ...
- Object源码解析(JDK1.8)
package java.lang; public class Object { /** * 一个本地方法,具体是用C(C++)在DLL中实现的,然后通过JNI调用 */ private static ...
- Object源码阅读
native修饰符:所修饰的方法的实现是由非java代码实现的 /** * 一个java程序如果想调用本地方法,需要执行两个步骤 * 1.通过system.loadLibrary()将包含本地方法实现 ...
随机推荐
- Spring Cloud Eureka源码分析---服务注册
本篇我们着重分析Eureka服务端的逻辑实现,主要涉及到服务的注册流程分析. 在Eureka的服务治理中,会涉及到下面一些概念: 服务注册:Eureka Client会通过发送REST请求的方式向Eu ...
- IntelliJ IDEA 配置Maven仓库
1. 下载Maven 官方地址:http://maven.apache.org/download.cgi 2. 修改本地仓库路径 3. 设置环境变量 MAVEN_HOME: E:\DevelopEnv ...
- idea 2019 1 spring boot 启动报错 An incompatible version [1.2.12] of the APR based Apache Tomcat Native library is installed, while Tomcat requires version [1.2.14]
1.构建一个简单springboot工程,日志打印报错内容如下: 15:38:28.673 [main] DEBUG org.springframework.boot.devtools.setting ...
- xml 需要转义的字符
XML实体中不允许出现"&","<",">"等特殊字符,否则XML语法检查时将出错,如果编写的XML文件必须包含这些字符 ...
- loadrunner常用web动作函数
web_custom_request ---允许使用任何http请求方法 脚本一: web_custom_request("baidu_request","URL=ht ...
- nginx篇高级之优化整理
优化思路: 一.修改连接数和工作线程让其支持更多的并发量. worker_processes 2; //与CPU核心数量一致 worker_connections ...
- docker compose网络设置
(系统:Centos 7.4 ,docker 版本:18.03.1-ce, docker-compose version 1.18.0) cat docker-compose.yml version: ...
- NOIP的模板--考前复习
距离NOIP还有25天 可以去放弃一些巨难得题目去搞一些模板了 -------在校老师的原话 一·快排 虽然可以手打,最好用STL,里面有很多优化,会快很多 #include<iostream& ...
- 11、pytest -- 测试的参数化
目录 1. @pytest.mark.parametrize标记 1.1. empty_parameter_set_mark选项 1.2. 多个标记组合 1.3. 标记测试模块 2. pytest_g ...
- 模块参数,系统调用,字符设备编程重要数据结构,设备号的申请与注册,关于cdev的API
1.模块参数 应用编程: int main(int argc, char *argv[]) { } ./a.out xxx yyy zzz ...