Java 中 `==` 和 `equals()` 的区别详解

news/2024/9/17 7:54:43/ 标签: java

在 Java 编程中,==equals() 是两种常用于比较变量和对象的方法。尽管它们都可以用来比较,但它们的作用和使用场景是不同的。本文将深入探讨它们之间的区别,并通过示例解释如何正确使用它们。

1. == 操作符

什么是 ==

== 是 Java 中的比较操作符,用于比较两个变量或对象的内存地址数值

  • 基本数据类型== 用于比较变量的数值是否相等。
  • 引用数据类型== 用于比较两个对象的引用地址是否相同,判断它们是否指向同一个对象。

示例 1:== 比较基本数据类型

java">int a = 5;
int b = 5;
System.out.println(a == b);  // 输出:true,因为 a 和 b 的值都是 5

示例 2:== 比较引用类型

java">String str1 = new String("hello");
String str2 = new String("hello");System.out.println(str1 == str2);  // 输出:false,因为 str1 和 str2 是不同的对象,内存地址不同

尽管 str1str2 内容相同,但 == 比较的是它们在内存中的地址,因此结果为 false


2. equals() 方法

什么是 equals()

equals()Object 类中的方法,默认情况下也用于比较两个对象的引用地址,即判断两个对象是否为同一个对象。然而,许多类(如 StringInteger)都会重写 equals() 方法,使其能够比较对象的内容

示例 1:equals() 比较字符串内容

java">String str1 = new String("hello");
String str2 = new String("hello");System.out.println(str1.equals(str2));  // 输出:true,因为 `String` 类重写了 `equals()`,比较的是字符串内容

String 类中,equals() 方法被重写为比较字符串的内容,因此尽管 str1str2 是不同的对象,但它们的内容相同,equals() 返回 true

示例 2:equals() 的默认行为

如果自定义的类没有重写 equals() 方法,则会继承 Object 类的默认实现,比较的是引用地址。

java">class Person {String name;Person(String name) {this.name = name;}
}Person p1 = new Person("Alice");
Person p2 = new Person("Alice");System.out.println(p1.equals(p2));  // 输出:false,因为 `Person` 没有重写 `equals()`,默认比较引用地址

尽管 p1p2name 属性相同,但它们是不同的对象,因此 equals() 默认返回 false


3. ==equals() 的区别总结

区别点==equals()
比较的内容基本数据类型:比较值。
引用类型:比较引用地址。
比较对象内容(如果类未重写 equals(),则与 == 类似,比较地址)。
适用的类型基本数据类型和引用类型。仅适用于引用类型。
能否重载不能重载。可以重写,通常在类中重写 equals() 以比较对象内容。
常见使用场景基本数据类型的值比较或判断两个引用是否指向同一对象。比较两个对象的内容是否相等(如 StringInteger 类)。

4. ==equals() 在字符串中的区别

String 是 Java 中最常见的引用类型之一。由于 String 类重写了 equals(),使得两个字符串对象的比较基于它们的内容,而不仅仅是内存地址。

示例:字符串池和 ==

Java 中有一个字符串池机制,字面量字符串会存储在池中。如果两个字面量字符串相同,它们会共享同一块内存,因此使用 == 比较时结果为 true

java">String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2);        // 输出:true,因为 s1 和 s2 指向相同的字符串池中的地址
System.out.println(s1.equals(s2));   // 输出:true,因为内容相同

然而,用 new 关键字创建的字符串每次都会创建新的对象,即使内容相同,== 也会返回 false,因为它们是不同的对象。

java">String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2);        // 输出:false,因为它们是不同的对象
System.out.println(s1.equals(s2));   // 输出:true,因为内容相同

5. 如何重写 equals() 方法

在自定义类中,如果希望根据对象的内容而不是内存地址来判断两个对象是否相等,通常需要重写 equals() 方法。

示例:重写 equals()

java">class Person {String name;int age;Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic boolean equals(Object obj) {if (this == obj) return true;if (obj == null || getClass() != obj.getClass()) return false;Person person = (Person) obj;return age == person.age && name.equals(person.name);}
}Person p1 = new Person("Alice", 25);
Person p2 = new Person("Alice", 25);System.out.println(p1.equals(p2));  // 输出:true,因为内容相同

在这个例子中,Person 类重写了 equals() 方法,以根据 nameage 判断对象是否相等。


6. hashCode()equals() 的关系

在 Java 中,hashCode()equals() 之间有一个重要的约定:如果两个对象根据 equals() 是相等的,那么它们的 hashCode() 值也必须相等。否则,在使用哈希表(如 HashMapHashSet)时会出现问题。

如果重写了 equals(),通常也需要重写 hashCode(),以确保对象在集合中的正确行为。

示例:重写 equals()hashCode()

java">class Person {String name;int age;Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic boolean equals(Object obj) {if (this == obj) return true;if (obj == null || getClass() != obj.getClass()) return false;Person person = (Person) obj;return age == person.age && name.equals(person.name);}@Overridepublic int hashCode() {return Objects.hash(name, age);}
}

结语

  • ==:用于比较基本数据类型的值或引用类型的内存地址。
  • equals():用于比较引用类型的内容(需重写)。

理解 ==equals() 的区别和适用场景,是掌握 Java 编程的关键。通过正确使用它们,你可以避免常见的逻辑错误,并编写更加健壮的代码。


http://www.ppmy.cn/news/1522755.html

相关文章

24并发设计模式——线程池模式

一、线程池模式介绍 线程池模式(Thread Pool Pattern)是一种并发设计模式,用于管理和循环使用线程资源以处理大量任务。它旨在提高系统性能和资源利用率,特别是在需要频繁创建和销毁线程的环境中。 1、线程池模式结构图 线程池管…

wmv怎么转换成视频mp4?简单的几种视频格式转换方法

wmv怎么转换成视频mp4?在数字媒体日益普及的今天,我们经常会遇到需要转换视频格式的情况。wmv格式,由微软开发,广泛用于Windows平台上播放视频。尽管wmv格式在Windows系统中表现优异,但其兼容性在其他操作系统或设备上…

为什么我选择这款PR剪辑软件?打工人亲测好用!

现在大家都爱看短视频和Vlog,要是你会剪辑视频,那可就牛了。不管是出去玩拍的视频,还是工作需要,都能派上用场。我就是个爱旅行、爱剪辑的发烧友,今天给你们推荐三款特别好用的视频剪辑软件,尤其是PR剪辑&a…

Android 串口数据分包处理

/* class PacketHandler { private static final byte PACKET_START 0x79; // 假设包的开始标记为0x79 private static final byte PACKET_END 0x0D; // 假设包的结束标记为0x0D private static ByteArrayOutputStream buffer new ByteArrayOutputStream();public static v…

【前端】中断请求的方式

一 使用 Axios 和取消令牌 1.步骤: 初始化取消源,创建CancelToken const source axios.CancelToken.source();传递cancelToken, 发起请求 axios.get(/api/data, {cancelToken: source.token });触发取消请求 source.cancel(操作被取消);判断错误是否由于取消请求操作引起…

Vue.js 组件化开发:父子组件通信与组件注册详解

Vue.js 组件化开发:父子组件通信与组件注册详解 简介: 在 Vue.js 的开发中,组件是构建应用的重要基础。掌握组件的创建与使用,尤其是父子组件的通信和组件的注册与命名,是开发中不可或缺的技能。本文将详细探讨这些内容…

【前端】CSS控制style样式失效

在CSS中,可以通过几种方式控制或禁用特定的style样式。 使用all: unset来重置所有可继承的属性,并清除所有的样式: .element {all: unset;} 使用inherit值来使属性获取其父元素的值: .element {color: inherit;font-size: inh…

用Unity2D制作一个人物,实现移动、跳起、人物静止和动起来时的动画:中(人物移动、跳起、静止动作)

上回我们学到创建一个地形和一个人物,今天我们实现一下人物实现移动和跳起,依次点击,我们准备创建一个C#文件 创建好我们点击进去,就会跳转到我们的Vision Studio,然后输入这些代码 using UnityEngine;public class M…

Vue 使用接口返回的背景图片和拼图图片进行滑动拼图验证

一、背景 前两天发了一篇 vue-monoplasty-slide-verify 滑动验证码插件使用及踩坑_vue-monoplasty-slide-verify 引用后不显示-CSDN博客 这两天项目又需要通过接口校验,接口返回了背景图片和拼图图片,于是在网上找了一篇帖子,vue 图片滑动…

Apache Ignite 在处理大规模数据时有哪些优势和局限性?

Apache Ignite 在处理大规模数据时的优势和局限性可以从以下几个方面进行分析: 优势 高性能:Ignite 利用内存计算的优势,实现了极高的读写性能,通过分布式架构,它可以将数据分散到多个节点上,从而实现了并…

JavaEE-HTTPHTTPS

目录 HTTP协议 一、概念 二、http协议格式 http请求报文 http响应报文 URL格式 三、认识方法 四、认识报头 HTTP响应中的信息 HTTPS协议 对称加密 非对称加密 中间人攻击 解决中间人攻击 HTTP协议 一、概念 HTTP (全称为 "超⽂本传输协议") 是⼀种应⽤…

2024华为OD机试真题-反射计数Python-C卷D卷-200分

2024华为OD机试最新E卷题库-(C卷+D卷+E卷)-(JAVA、Python、C++) 目录 题目描述 输入描述 输出描述 用例1 题目解析 代码 题目描述 给定一个包含 0 和 1 的二维矩阵。 给定一个初始位置和速度,一个物体从给定的初始位置出发,在给定的速度下进行移动,遇到矩阵的边缘则…

分布式部署①

📑打牌 : da pai ge的个人主页 🌤️个人专栏 : da pai ge的博客专栏 ☁️宝剑锋从磨砺出,梅花香自苦寒来 1. 需要部署的服务 Nacos 理论上,应…

仕考网:事业编面试全流程介绍

1.进入考场 工作人员会检查考生的身份证、准考证以及随身携带物品,可以带食物和水 2.进入候考室 进入候考室,工作人员会再次确认考生信息 3.抽签 考生到齐后,工作人员会组织考生抽签,登记抽签序号、信息确认、发放号码牌 4.…

【Android】使用和风天气API获取天气数据吧!(天气预报系列之一)

【Android】使用和风天气API获取天气数据吧!(天气预报系列之一) 古话说得好,要有天气预报,首先需要有天气,和预报。 今天给大家介绍一个好用的天气预报API:和风天气。以及webAPI的使用方法~&a…

React 应用中集成 Ace Editor

安装 React-Ace 首先,你需要安装 react-ace 和 ace-builds(它包含 Ace Editor 的核心文件): pnpm install react-ace ace-builds用法: import React from react; import AceEditor from react-ace;// 引入你需要的 …

从“游戏科学”到玄机科技:《黑神话:悟空》的视角打开动漫宇宙

近日,中国游戏界迎来了一场前所未有的盛事——由游戏科学公司开发的《黑神话:悟空》正式上线,并迅速成为全球玩家热议的焦点。在居高不下的讨论热度中,有人说他的成功在于对《西游记》为背景进行改编,对原著进行了分析…

es安装ik分词器

下载分词器 首先确定es对应的版本(假设版本是7.10.0)根据版本下载指定的分词器 开始安装 在线安装 ./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.10.0/elasticsearch-analysis-ik-…

如何在 Java 中实现线程安全的单例模式?

单例模式是一种常用的软件设计模式,它确保一个类只有一个实例,并提供一个全局访问点。 在多线程环境下,确保单例模式的线程安全性是非常重要的,因为多个线程可能会同时尝试创建实例,导致实例不唯一的问题。 单例模式…

[数据集][目标检测]翻越栏杆行为检测数据集VOC+YOLO格式512张1类别

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):512 标注数量(xml文件个数):512 标注数量(txt文件个数):512 标注类别…