【Java 学习】Java的生命之源:走进Object类的神秘花园,解密Object类的背后故事

【Java 学习】Java的生命之源:走进Object类的神秘花园,解密Object类的背后故事
💬 欢迎讨论:如对文章内容有疑问或见解,欢迎在评论区留言,我需要您的帮助!

👍 点赞、收藏与分享:如果这篇文章对您有所帮助,请不吝点赞、收藏或分享,谢谢您的支持!

🚀 传播技术之美:期待您将这篇文章推荐给更多对需要学习Java语言、低代码开发感兴趣的朋友,让我们共同学习、成长!

1. Object 类

1.1 为什么所有类都继承 Object 类?

在Java中,Object 类是所有类的根类。也就是说,所有的类(包括用户自定义的类)都直接或间接继承自 Object 类。这是因为在 Java 中,Object 是所有类层次结构的最顶端类。

为什么所有类都继承 Object 类?

  1. 统一的根基:Java 为了实现统一性,决定所有类都直接或间接继承自 Object 类。这意味着每个类都可以拥有 Object 类的一些通用方法,这样使得不同类型的对象可以被处理得更加一致。
  2. 常用方法:Object 类提供了一些常用方法,这些方法被所有类继承。比如:这些方法大多数类都会使用,或者根据需要进行重写,以便提供不同的行为。
    • toString():返回对象的字符串表示。
    • equals(Object obj):判断两个对象是否相等。
    • hashCode():返回对象的哈希码。
    • clone():创建并返回当前对象的副本。
    • getClass():返回对象的类信息。
    • notify(), notifyAll(), wait():用于多线程编程。
  3. 多态性和泛型:Java 中的多态性和泛型常常依赖于 Object 类。例如,在方法中接受一个 Object 类型的参数,就可以传入任何类型的对象。而且通过 Object 类的方法,可以对不同类型的对象进行统一的操作。

1.2 统一操作–举例

  1. toString() 方法
    toString() 方法是 Object 类提供的一个方法,默认返回对象的类名加上对象的哈希码的字符串表示。但是你可以在自己的类中重写这个方法,使其返回更具意义的信息。
classPerson{String name;int age;Person(String name,int age){this.name = name;this.age = age;}@OverridepublicStringtoString(){return"Person{name='"+ name +"', age="+ age +"}";}}classCar{String brand;String model;Car(String brand,String model){this.brand = brand;this.model = model;}@OverridepublicStringtoString(){return"Car{brand='"+ brand +"',+ model +"'}";}}publicclassMain{publicstaticvoidmain(String[] args){Person person =newPerson("John",30);Car car =newCar("Toyota","Camry");// 使用toString()输出对象的字符串表示System.out.println(person.toString());// Person{name='John', age=30}System.out.println(car.toString());// Car{brand='Toyota', model='Camry'}}}
  1. equals() 方法
    equals() 方法用于判断两个对象是否“相等”,默认的实现是比较对象的内存地址,但你可以重写它来根据类的字段比较对象的内容。
classPerson{String name;int age;Person(String name,int age){this.name = name;this.age = age;}@Overridepublicbooleanequals(Object obj){if(this== obj)returntrue;// 判断是否是同一对象if(obj ==null||getClass()!= obj.getClass())returnfalse;Person person =(Person) obj;return age == person.age && name.equals(person.name);}}publicclassMain{publicstaticvoidmain(String[] args){Person person1 =newPerson("John",30);Person person2 =newPerson("John",30);Person person3 =newPerson("Alice",25);// 使用equals()比较对象是否相等System.out.println(person1.equals(person2));// trueSystem.out.println(person1.equals(person3));// false}}
  1. hashCode() 方法
    hashCode() 方法用于返回对象的哈希值,通常与 equals() 配合使用。如果两个对象相等,那么它们的 hashCode() 也应该相等。
classPerson{String name;int age;Person(String name,int age){this.name = name;this.age = age;}@Overridepublicbooleanequals(Object obj){if(this== obj)returntrue;if(obj ==null||getClass()!= obj.getClass())returnfalse;Person person =(Person) obj;return age == person.age && name.equals(person.name);}@OverridepublicinthashCode(){return31* name.hashCode()+ age;}}publicclassMain{publicstaticvoidmain(String[] args){Person person1 =newPerson("John",30);Person person2 =newPerson("John",30);// 使用hashCode()获取对象的哈希值System.out.println(person1.hashCode());// 打印哈希值System.out.println(person2.hashCode());// 打印哈希值System.out.println(person1.equals(person2));// true}}

1.3 Object 类中的所有方法

下图就是Object类,在包java.lang

在这里插入图片描述


如果把Object类中的注释全部删去,Object类的代码如下:

/* * Copyright (c) 1994, 2022, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */packagejava.lang;importjdk.internal.misc.Blocker;importjdk.internal.vm.annotation.IntrinsicCandidate;publicclassObject{@IntrinsicCandidatepublicObject(){}@IntrinsicCandidatepublicfinalnativeClass<?>getClass();@IntrinsicCandidatepublicnativeinthashCode();publicbooleanequals(Object obj){return(this== obj);}@IntrinsicCandidateprotectednativeObjectclone()throwsCloneNotSupportedException;publicStringtoString(){returngetClass().getName()+"@"+Integer.toHexString(hashCode());}@IntrinsicCandidatepublicfinalnativevoidnotify();@IntrinsicCandidatepublicfinalnativevoidnotifyAll();publicfinalvoidwait()throwsInterruptedException{wait(0L);}publicfinalvoidwait(long timeoutMillis)throwsInterruptedException{long comp =Blocker.begin();try{wait0(timeoutMillis);}catch(InterruptedException e){Thread thread =Thread.currentThread();if(thread.isVirtual()) thread.getAndClearInterrupt();throw e;}finally{Blocker.end(comp);}}// final modifier so method not in vtableprivatefinalnativevoidwait0(long timeoutMillis)throwsInterruptedException;publicfinalvoidwait(long timeoutMillis,int nanos)throwsInterruptedException{if(timeoutMillis <0){thrownewIllegalArgumentException("timeoutMillis value is negative");}if(nanos <0|| nanos >999999){thrownewIllegalArgumentException("nanosecond timeout value out of range");}if(nanos >0&& timeoutMillis <Long.MAX_VALUE){ timeoutMillis++;}wait(timeoutMillis);}@Deprecated(since="9", forRemoval=true)protectedvoidfinalize()throwsThrowable{}}

我们可以从Object类中看到我们常用的toString方法、clone方法。

2. Object 类中的 clone() 方法

2.1 clone方法的定义和用途

Object 类中的 clone() 方法用于创建当前对象的一个副本(即对象的浅拷贝)。它是一个受保护的方法(用protected修饰),所以默认情况下只有 Object 类本身及其子类可以调用。在实际开发中,clone() 方法常常被重写,以便提供更灵活的复制功能。

clone方法的声明如下:

protectedObjectclone()throwsCloneNotSupportedException;

说明

  • 返回值类型:Object 类型。返回的是当前对象的副本,因此返回值需要被强制转换为具体的类型。
  • 异常:CloneNotSupportedException,如果对象的类没有实现 Cloneable 接口,调用 clone() 方法时会抛出此异常。

clone() 方法是 Object 类中定义的,用于返回一个与当前对象相同的副本。在默认实现中,它是浅拷贝,意味着它会复制对象的基本数据类型字段,但如果对象包含引用类型的字段,那么这些字段依然指向原来的对象。

2.2 浅拷贝与深拷贝

浅拷贝(Shallow Copy):拷贝对象时,对于基本类型的字段会进行复制,而对于引用类型的字段,会复制引用地址,也就是说,源对象和拷贝对象共享同一个引用。

解释:
在 Java 中,clone() 方法是 Object 类提供的一个原生方法。这个方法并不是直接通过构造函数来创建一个新的对象,而是通过底层的 内存复制 技术来快速创建一个与原对象相同类型的新对象。
Object 类的 clone() 方法默认会调用 native 实现,这个实现通过操作内存直接创建一个新的对象实例,并将原对象的字段内容复制到新的实例中。这意味着 clone() 方法创建的对象是一个浅拷贝,字段的值被复制,但如果字段是引用类型,那么新对象的字段仍然指向原对象的同一内存地址。

深拷贝(Deep Copy):不仅复制对象本身,还会递归地复制对象中的所有引用类型字段,使得源对象和拷贝对象之间不再共享任何引用。

clone() 方法默认是进行浅拷贝的,如果需要实现深拷贝,则需要重写 clone() 方法并手动处理引用类型字段的复制。

2.3 总结

总结

  • clone() 是通过 Object 类的 clone() 方法实现的,底层通过内存复制技术创建新对象。
  • clone() 会复制原对象的字段值,对于基本类型字段是值复制,对于引用类型字段是引用复制。
  • clone() 返回的是一个新对象,但新对象与原对象的引用类型字段指向同一内存地址,属于浅拷贝。
  • 调用 clone() 不会触发构造函数的执行。

Read more

C++ 波澜壮阔 40 年:从 C with Classes 到现代 C++ 的进化史诗

C++ 波澜壮阔 40 年:从 C with Classes 到现代 C++ 的进化史诗

🔥@晨非辰Tong: 个人主页 👀专栏:《数据结构与算法入门指南》、《C++学习之旅》 💪学习阶段:C语言、数据结构与算法初学者 ⏳“人理解迭代,神理解递归。” 文章目录 * 引言 * 一、波澜壮阔的C++“发家”历史 * 1. 1 C with Classes (1979-1983)-起源 * 1.2 早期发展:C++的"++"从何来(1983-1989) * 1.3 标准化与成熟(1990-1998) * 1.4 现代化浪潮(2011-至今) * 二、推荐C++学习参考网站、好用书籍 * 三、梦开始的地方:C++的第一个程序 * 3.

By Ne0inhk
Windows下MATLAB与C/C++混合编程:DLL生成与调用实战

Windows下MATLAB与C/C++混合编程:DLL生成与调用实战

Windows下MATLAB与C/C++混合编程:DLL生成与调用实战 在科学计算与工程开发中,MATLAB凭借其便捷的矩阵运算和可视化能力广受青睐,但面对大规模数据处理或高性能算法时,C/C++的执行效率优势无可替代。将二者结合,通过动态链接库(DLL) 实现混合编程,既能发挥MATLAB的易用性,又能借助C/C++提升核心代码性能。本文将手把手教你在Windows环境下完成从C/C++ DLL编写、编译到MATLAB调用的全流程,附带完整代码与避坑指南! 一、核心原理与准备工作 1. 核心逻辑 C/C++编译生成的DLL文件包含可被外部程序调用的函数,通过__declspec(dllexport)声明导出函数,并使用extern "C"指定C链接规范,避免C++的名称修饰(name mangling)问题,确保MATLAB能正确识别函数名。 MATLAB通过loadlibrary函数加载DLL,解析函数接口后,使用calllib函数调用目标函数,实现数据交互。 2.

By Ne0inhk
【Linux/C++多进程篇(二) 】万字解析从“传纸条”到“建仓库”:一文读懂linux系统编程之进程间通信 (IPC)

【Linux/C++多进程篇(二) 】万字解析从“传纸条”到“建仓库”:一文读懂linux系统编程之进程间通信 (IPC)

⭐️在这个怀疑的年代,我们依然需要信仰。 个人主页:YYYing. ⭐️Linux/C++进阶系列专栏:【从零开始的linux/c++进阶编程】 系列上期内容:【Linux/C++多进程篇(一) 】C/C++ 程序中神奇的“分身术” 系列下期内容:【Linux/C++多线程篇(一) 】多线程编程入门 目录 前言: 进程间通信(IPC) 一、进程间通信的基础概念 二、内核提供的通信方式 2.1、无名管道  📖 无名管道的API  📖 代码案例 2.2、有名管道  📖 有名管道的API  📖 代码案例 2.3、管道特点 2.4、信号  📖 信号相关概念

By Ne0inhk
Qt步进电机上位机控制程序源代码:跨平台C/C++编写,支持多种端口类型与详细注释

Qt步进电机上位机控制程序源代码:跨平台C/C++编写,支持多种端口类型与详细注释

Qt步进电机上位机控制程序源代码Qt跨平台C/C++语言编写 支持串口Tcp网口Udp网络三种端口类型 提供,提供详细注释和人工讲解 1.功能介绍: 可控制步进电机的上位机程序源代码,基于Qt库,采用C/C++语言编写。 支持串口、Tcp网口、Udp网络三种端口类型,带有调试显示窗口,接收数据可实时显示。 带有配置自动保存功能,用户的配置数据会自动存储,带有超时提醒功能,如果不回复则弹框提示。 其中三个端口,采用了类的继承与派生方式编写,对外统一接口,实现多态功能,具备较强的移植性。 2.环境说明: 开发环境是Qt5.10.1,使用Qt自带的QSerialPort,使用网络的Socket编程。 源代码中包含详细注释,使用说明,设计文档等。 请将源码放到纯英文路径下再编译。 3.使用介绍: 可直接运行在可执行程序里的exe文件,操作并了解软件运行流程。 本代码产品特点: 1、尽量贴合实际应用,细节考虑周到。 2、注释完善,讲解详细,还有相关扩展知识点介绍。

By Ne0inhk