Java中的object类与objects类

Java中的Object类和Objects类在Java类库中扮演着不同的角色,它们之间存在明显的区别。

Object类

  1. 基础与根源
    • Object类是Java类层次结构的根类。这意味着Java中的每一个类(除了Object类本身)都直接或间接地继承自Object类。
    • Object类位于java.lang包中,这个包是Java的核心包之一,自动被所有的Java程序所导入。
  2. 方法与属性
    • Object类提供了一系列的方法,如equals(Object obj)toString()hashCode()clone()finalize()getClass()notify()notifyAll()wait()wait(long timeout)wait(long timeout, int nanos)等。
    • Object类没有显式声明的属性(字段),因为它主要是作为一个基类来提供通用的方法。
  3. 功能
    • Object类的方法为所有Java对象提供了基本的行为。例如,equals()用于比较两个对象是否相等,toString()用于返回对象的字符串表示,hashCode()用于生成对象的哈希码等。

Objects类

  1. 工具类
    • Objects类是一个工具类,位于java.util包中。它提供了一系列静态方法,用于处理对象,特别是为了避免空指针异常(NullPointerException)和提高代码的可读性。
    • Objects类自Java 7引入,是JDK的一部分。
  2. 方法与功能
    • Objects类提供了如isNull(Object obj)nonNull(Object obj)requireNonNull(Object obj)requireNonNull(Object obj, String message)equals(Object a, Object b)deepEquals(Object a, Object b)hashCode(Object o)toString(Object o)toString(Object o, String nullDefault)等方法。
    • 这些方法大多是null安全的,即它们能够优雅地处理null值,避免在比较或调用方法时抛出空指针异常。
  3. 与Object类的区别
    • 位置与目的Object类是类层次结构的根,提供基本的行为;而Objects类是一个工具类,提供处理对象的实用方法。
    • 方法与实现Object类的方法通常是实例方法,需要在对象上调用;而Objects类的方法全部是静态的,可以直接通过类名调用。

先介绍一下 object类常见方法:

1.toString(Object o)

Objects.toString(Object o)方法用于生成对象的字符串表示。如果对象不为null,则调用对象的toString方法;如果对象为null,则返回字符串"null"。这个方法的好处在于它可以安全地处理null值,避免了在调用toString方法前进行null检查的需要。

示例代码

import java.util.Objects;  public class Person {  private String name;  public Person(String name) {  this.name = name;  }  @Override  public String toString() {  // 使用Objects.toString来安全地生成字符串表示  return "Person{" +  "name='" + Objects.toString(name) + '\'' +  '}';  }  public static void main(String[] args) {  Person person = new Person("Alice");  System.out.println(person); // 输出: Person{name='Alice'}  Person nullPerson = null;  System.out.println(Objects.toString(nullPerson)); // 输出: null  }  
}

2. equals(Object obj) 方法

equals(Object obj) 方法用于比较两个对象是否相等。在Object类中,equals()方法默认的实现是比较两个对象的引用是否指向内存中的同一个位置(即是否是同一个对象)。但是,在自定义类中,通常会根据对象的实际内容来重写equals()方法。

在Java中,重写equals方法以比较两个对象的内容是否相同是一个常见的需求。当你定义了一个类,并且希望基于类的某些字段(或全部字段)来判断两个对象是否相等时,就需要重写equals方法。同时,为了保持hashCode方法的一致性约定,通常也需要重写hashCode方法。

下面是一个基于自定义类Person的例子,该类包含nameage两个字段,并且重写了equalshashCode方法以基于这两个字段的内容来判断对象是否相等:

import java.util.Objects;  public class Person {  private String name;  private int age;  // 构造函数  public Person(String name, int age) {  this.name = name;  this.age = age;  }  // Getter 和 Setter 省略  // 重写 equals 方法  @Override  public boolean equals(Object obj) {  // 检查是否为同一个对象的引用  if (this == obj) return true;  // 检查是否为 null 或者类型是否相同  if (obj == null || getClass() != obj.getClass()) return false;  // 类型转换  Person person = (Person) obj;  // 比较字段  return age == person.age &&  Objects.equals(name, person.name);  }  // 重写 hashCode 方法  @Override  public int hashCode() {  return Objects.hash(name, age);  }  // toString 方法,方便输出查看  @Override  public String toString() {  return "Person{" +  "name='" + name + '\'' +  ", age=" + age +  '}';  }  // 主方法,用于测试  public static void main(String[] args) {  Person p1 = new Person("Alice", 30);  Person p2 = new Person("Alice", 30);  Person p3 = p1; // 同一个引用  System.out.println(p1.equals(p2)); // 输出 true  System.out.println(p1.equals(p3)); // 输出 true  System.out.println(p1.equals(null)); // 输出 false,因为null不是Person类型  System.out.println(p1.hashCode() == p2.hashCode()); // 输出 true,因为内容相同  // 使用 HashSet 测试  HashSet<Person> set = new HashSet<>();  set.add(p1);  set.add(p2); // 这行不会添加新的元素,因为 p1 和 p2 内容相同  System.out.println(set.size()); // 输出 1  }  
}  // 注意:需要导入 HashSet  
// import java.util.HashSet;

 

在这个例子中,equals方法首先检查调用它的对象(this)和参数对象(obj)是否是同一个对象引用(通过==)。然后,它检查参数对象是否为null或者是否属于与调用对象不同的类(通过getClass()方法)。接下来,它将参数对象强制转换为正确的类型(在这个例子中是Person),并比较两个对象的字段值。

hashCode方法使用Objects.hash方法来生成一个基于nameage的哈希码,这有助于在基于哈希的集合中保持equalshashCode的一致性。

最后,main方法中的测试代码演示了如何使用重写后的equalshashCode方法,并展示了它们如何影响基于哈希的集合(如HashSet)的行为。

有人会问为什么要重写 hashCode 方法? 

在Java中,虽然从技术上讲你可以只重写equals方法而不重写hashCode方法,但在实践中这通常是不推荐的,原因与Java集合框架(Collections Framework)的某些类(特别是基于哈希的类,如HashSetHashMapHashtableLinkedHashSet等)的行为密切相关。

这些基于哈希的集合类使用哈希码(hash code)来优化查找、插入和删除操作的速度。它们通过调用对象的hashCode方法来获取哈希码,并使用这个哈希码来快速定位元素在集合中的存储位置(即“桶”或“槽”)。

当你重写equals方法时,你实际上是在改变对象相等性的判断逻辑。如果两个对象通过equals方法被认为是相等的,那么它们必须产生相同的哈希码(即hashCode方法的返回值必须相同),这是hashCode方法的一般约定(contract)所要求的。

如果你只重写了equals方法而没有重写hashCode方法,那么可能会出现以下情况:

  1. 违反hashCode的一般约定:如果两个相等的对象(即equals方法返回true的对象)没有相同的哈希码,那么这违反了hashCode方法的一般约定。

  2. 破坏基于哈希的集合的行为:在基于哈希的集合中,如果两个相等的对象没有相同的哈希码,那么这些集合可能无法正确地存储、检索或删除这些对象。例如,在HashSet中,即使两个对象通过equals方法比较是相等的,如果它们的哈希码不同,它们也可能被存储在不同的位置,导致HashSet错误地认为它们是不同的对象。

  3. 导致性能问题:即使基于哈希的集合在内部能够处理哈希冲突(即不同对象具有相同哈希码的情况),但如果相等的对象没有相同的哈希码,那么这种冲突可能会更加频繁,从而降低集合的性能。

因此,当你重写equals方法时,通常也应该重写hashCode方法,以确保相等的对象具有相同的哈希码,从而维护hashCode方法的一般约定,并避免在基于哈希的集合中出现问题。这是Java编程中的一个重要实践。


在IntelliJ IDEA(简称IDEA)中,快捷键Alt+Insert。可以选择相应的内容直接简写。

或右键选择generate。


3. clone() 方法

clone() 方法用于创建并返回当前对象的一个副本。但是,Object类中的clone()方法是受保护的,并且是一个本地方法,这意味着它依赖于具体实现(通常是JVM)。要在自定义类中使用clone()方法,你需要:

  1. 实现Cloneable接口(这是一个标记接口,不包含任何方法,但它指示Objectclone()方法可以被该类的对象调用)。
  2. 在你的类中重写clone()方法,并调用super.clone()
public class Person implements Cloneable {  // 成员变量、构造函数、getter和setter略  @Override  protected Person clone() throws CloneNotSupportedException {  return (Person) super.clone(); // 调用Object类的clone()方法  }  public static void main(String[] args) throws CloneNotSupportedException {  Person original = new Person();  Person copy = original.clone();  // 注意:这里只是浅拷贝,如果Person类包含对其他可变对象的引用,则这些引用会被共享  }  
}

 请注意,上述clone()方法的实现是浅拷贝(shallow copy)。如果你需要深拷贝(deep copy),你需要手动实现深拷贝的逻辑,包括递归地拷贝所有引用到的可变对象。


再介绍一下 objects类常见方法:

1.Objects.equals(Object a, Object b)

在Java的Objects类中,equals方法是一个静态方法,用于比较两个对象是否相等。这个方法特别有用,因为它提供了一种类型安全的方式来比较两个对象,同时避免了直接调用null.equals(Object)时可能发生的NullPointerException

Objects.equals(Object a, Object b)方法的工作原理如下:

  1. 如果两个参数都是null,则方法返回true
  2. 如果其中一个参数是null而另一个不是,则方法返回false
  3. 否则,它返回a.equals(b)的结果。

这里是一个使用Objects.equals方法的代码示例:

import java.util.Objects;  public class ObjectsEqualsExample {  public static void main(String[] args) {  // 测试两个null对象  String str1 = null;  String str2 = null;  System.out.println(Objects.equals(str1, str2)); // 输出: true  // 测试一个null对象和一个非null对象  String str3 = "Hello";  System.out.println(Objects.equals(str1, str3)); // 输出: false  // 测试两个相同的非null对象  String str4 = "Hello";  System.out.println(Objects.equals(str3, str4)); // 输出: true  // 测试两个不同的非null对象  String str5 = "World";  System.out.println(Objects.equals(str3, str5)); // 输出: false  // 示例:在自定义对象中使用Objects.equals进行比较  Person person1 = new Person("Alice", 30);  Person person2 = new Person("Alice", 30);  // 注意:这里的比较是基于引用,而不是内容。要比较内容,需要重写Person类的equals方法。  // 但为了演示Objects.equals的用法,我们假设这里只比较引用。  System.out.println(Objects.equals(person1, person2)); // 输出: false,因为person1和person2引用不同的对象  // 如果Person类重写了equals方法以比较内容,则应该使用person1.equals(person2)或Objects.equals(person1, person2)  // 来获得基于内容的比较结果。  }  // 一个简单的Person类示例  static class Person {  private String name;  private int age;  public Person(String name, int age) {  this.name = name;  this.age = age;  }  // 这里应该重写equals和hashCode方法,但为了简单起见,我们省略了它们。  }  
}

请注意,在上面的示例中,Person类没有重写equals方法,因此使用Objects.equals(person1, person2)将只比较两个Person对象的引用是否相同,而不是它们的内容。在实际应用中,如果你想要基于对象的内容来比较两个对象是否相等,你应该在类中重写equals方法(以及hashCode方法以保持一致性)。

然而,即使你没有重写equals方法,Objects.equals仍然是一个有用的工具,因为它可以避免在直接调用null.equals(Object)时可能发生的NullPointerException

注意:

public class Test1 {public static void main(String[] args) {String s1=null;String s2="xuboyuan";// System.out.println(s1.equals(s2));报错System.out.println(Objects.equals(s1,s2));//false}
}

在Java中,当你尝试调用一个null对象的任何方法时,包括equals()方法,都会抛出NullPointerException。这是因为null并不指向任何有效的对象实例,因此没有可以调用的方法。

在你的第一个示例中:

这行代码尝试调用s1equals()方法来与s2进行比较。但是,由于s1null,没有对象实例可以调用equals()方法,因此Java运行时环境会抛出一个NullPointerException

相反,在你的第二个示例中:

这里你使用了java.util.Objects类的equals()静态方法。这个方法是专门为处理可能为null的对象而设计的,它首先检查两个参数是否都为null,如果都是null则返回true;如果只有一个为null,则返回false;如果两个都不是null,则调用第一个参数的equals()方法与第二个参数进行比较。由于s1nulls2不是,所以Objects.equals(s1, s2)返回false,而不会抛出NullPointerException

这就是为什么第一个示例会报错而第二个示例不会的原因。Objects.equals()方法提供了一种安全的方式来比较可能为null的对象,避免了直接调用null对象的equals()方法时可能发生的异常。

2.isNull(Object obj)

检查对象是否为 null

Object obj = null;  
boolean isNull = Objects.isNull(obj); // 返回true

3.nonNull(Object obj)

检查对象是否不为 null

Object obj = "Hello";  
boolean nonNull = Objects.nonNull(obj); // 返回true

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/49414.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024年7月解决Docker拉取镜像失败的实用方案,亲测有效

在Ubuntu 16.04、Debian 8、CentOS 7系统中&#xff0c;若遇到Docker拉取镜像失败的问题&#xff0c;以下是一些亲测有效的解决方案&#xff1a; 配置加速地址 首先&#xff0c;创建Docker配置目录&#xff1a;sudo mkdir -p /etc/docker然后&#xff0c;编辑daemon.json文件…

C++客户端Qt开发——Qt窗口(对话框)

5.对话框 ①对话框介绍 对话框是GUI程序中不可或缺的组成部分。一些不适合在主窗口实现的功能组件可以设置在对话框中。对话框通常是一个顶层窗口&#xff0c;出现在程序最上层&#xff0c;用于实现短期任务或者简洁的用户交互。Qt常用的内置对话框有&#xff1a;QFiledialog…

【第四天】计算机网络知识 HTTP1.0,HTTP1.1与HTTP2.0的区别 HTTP3.0

HTTP1.0&#xff0c;HTTP1.1与HTTP2.0的区别 HTTP1.0 默认是短链接&#xff0c;可以强制开启长连接。HTTP1.1默认长连接。HTTP2.0采用多路复用。 HTTP1.0&#xff1a; 默认使用短链接&#xff0c;每次请求都需要建立一个TCP连接。它可以设置&#xff1a;Connection: keep-aliv…

利用OSMnx求路网最短路径并可视化(二)

书接上回&#xff0c;为了增加多路径的可视化效果和坐标匹配最近点来实现最短路可视化&#xff0c;我们使用图形化工具matplotlib结合OSMnx的绘图功能来展示整个路网图&#xff0c;并特别高亮显示计算出的最短路径。 多起终点最短路路径并计算距离和时间 完整代码#运行环境 P…

洛谷 P9854 [CCC 2008 J1] Body Mass Index

这题让我们计算出 BMI 值&#xff0c;随后判断属于哪个等级。 BMI 值计算公式&#xff1a; ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​。 BMI 范围 对应信息 …

【JVM基础08】——类加载器-说一下类加载的执行过程?

目录 1- 引言&#xff1a;类加载的执行过程1-1 类加载的执行过程是什么&#xff1f;(What) 2- ⭐核心&#xff1a;详解类加载的执行过程(How)2-1 加载——>加载到运行时数据区2-2 验证——>类的安全性检查2-3 准备——>为类变量分配内存并设置初始值2-4 解析——>把…

Web网页端IM产品RainbowChat-Web的v7.1版已发布

一、关于RainbowChat-Web RainbowChat-Web是一套Web网页端IM系统&#xff0c;是RainbowChat的姊妹系统&#xff08;RainbowChat是一套基于开源IM聊天框架 MobileIMSDK (Github地址) 的产品级移动端IM系统&#xff09;。 ► 详细介绍&#xff1a;http://www.52im.net/thread-2…

每天一个设计模式之职责链模式(第一天)

特别感谢刘伟老师&#xff0c;看他的书我学到了很多东西&#xff0c;从今天开始我要开始更新啦&#xff01; 在csdn个人博客来总结知识&#xff0c;把他们变成自己的能力。 对三&#xff0c;要不起&#xff0c;张三李四王五几个人在玩斗地主&#xff0c;过过过&#xff0c;一…

Codeforces Round 962 (Div. 3)

链接 C题&#xff1a; 思路&#xff1a; 直接暴力求每个字母的前缀和&#xff0c;对于区间l&#xff0c;r的最小操作就是区间不同数的一半&#xff0c;因为可以把一个数变成另一个不一样的数&#xff0c;一下抵消两个。 #include<bits/stdc.h> using namespace std; //…

MySQL中不等于筛选时会漏掉null值的问题

一、问题描述 MySQL中使用不等于进行筛选数据时&#xff0c;若筛选值为null&#xff0c;则该条数据不会被选中&#xff0c;如何解决该问题&#xff1f; 表示不等于的方式如下&#xff1a; ! <> not in二、案例验证 1、创建数据表 -- ---------------------------- -…

【2024最新版】Stable diffusion汉化版安装教程(附SD安装包),一键激活,永久免费!

目前广泛使用的Stable Diffusion Web UI简称(SDWebUI)是发布在开源平台Github上的一个Python项目,与通常的软件安装方法不同,这个项目并不是下载并安装即可使用的应用程序,而是需要准备执行环境,编译源码. 如果你是一个新手不会安装,现在可以直接使用一键启动包. 例如:国内的…

AI驱动的在线面试系统:技术革新与初步面试的新体验

一、引言 在数字化和智能化的时代背景下&#xff0c;人工智能&#xff08;AI&#xff09;技术正日益渗透到各行各业&#xff0c;为人们的生活和工作带来前所未有的变革。其中&#xff0c;AI驱动的在线面试系统&#xff0c;凭借其高效、便捷、公正等特性&#xff0c;逐渐成为企业…

ATF-541M4全解析(一)

目录 一、描述二、规格三、各参数最大值四、25℃下的典型值 一、描述 安华高科技 (Avago Technologies) 的 ATF-541M4 是一款高线性度、低噪声、单电源供电的E-PHEMT&#xff0c;封装在一个微型无引脚封装中。 ATF-541M4 的小尺寸和低外形使其非常适合用于混合模块和其他空间…

美团测开面经整理大汇总!!

大厂测开面经&#xff0c;加油加油&#xff0c;一周看一篇 美团测开面经美团测开暑期实习面经第二弹美团-地图服务部测开一面面经&#xff08;70min&#xff09;美团-优选事业部测开一面面经美团-优选事业部测开二面面经&#xff08;82min&#xff09;美团第一次测开笔试美团测…

matplotlib 画图函数,最常用的

并排显示2个图片 import os import numpy as np from PIL import Image import matplotlib.pyplot as pltimage1 Image.open(a.png) image2 Image.open(a2.png)# Create a figure with two subplots (1 row, 2 columns) fig, axes plt.subplots(1, 2, figsize(10, 5))# Di…

【Git-驯化】一文搞懂git中rm命令的使用技巧

【Git-驯化】一文搞懂git中rm命令的使用技巧 本次修炼方法请往下查看 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合&#xff0c;智慧小天地&#xff01; &#x1f387; 免费获取相关内容文档关注&#xff1a;微信公…

git学习笔记(总结了常见命令与学习中遇到的问题和解决方法)

前言 最近学习完git&#xff0c;学习过程中也遇到了很多问题&#xff0c;这里给大家写一篇总结性的博客&#xff0c;主要大概讲述git命令和部分难点问题&#xff08;简单的知识点这里就不再重复讲解了&#xff09; 一.git概述 1.1什么是git Git是一个分布式的版本控制软件。…

【推研小灶】复旦与南大之间:一次独特的计算机保研之旅

写在前面 上午10点填完志愿等待复试通知&#xff0c;利用这段时间记录一下我简短的夏令营和预推免。今年变为线下之后&#xff0c;部分学校的入营情况、考核方式有明显变化。加上CS方向保研名额总体变多&#xff0c;形势有点小乱&#xff0c;甚至填报系统都在9.29中秋节当天&a…

嵌入式C++、Raspberry Pi、LoRa和Wi-Fi技术、TensorFlow、ROS/ROS2:农业巡检数据导航机器人设计流程(代码示例)

随着科技的不断进步&#xff0c;农业领域也在逐渐向智能化发展。农业巡检机器人作为农业智能化的重要组成部分&#xff0c;能够自动化地监测农作物生长状况&#xff0c;提高农业管理的效率和精确度。本文将介绍一个基于Raspberry Pi和NVIDIA Jetson的农业巡检机器人&#xff0c…

【我的养猪日记】区块链游戏

剧情介绍 年少无知留给了故乡&#xff0c;谦卑有礼送给了远方&#xff0c;有工作的地方没家&#xff0c;有家的地方没工作&#xff0c;他乡留不下灵魂&#xff0c;故乡安不了肉身&#xff0c;从此便有了漂泊。在外漂泊数年的你每天过着&#xff0c;挤不完的公交地铁、交不完的房…