Java中对象比较的三种方式

2023-11-17

一. 针对对象值是否相等的比较

== 和 equals 的区别

当我们提到比较值的时候,大多数人都会想到 == ,因为在一般情况下,人们对于比较的概念中,数字比较的应用场景出现频率是最多的.
首先我们创建一个类,之后新建这个类的对象来进行比较验证.

class Student {
    public String name;
    public int score;
    
    public Student(String name, int score) {
        this.name = name;
        this.score = score;
    }
}
==

我们通常都用 == 来比较数字的大小,那如果用他来比较对象会是什么情况,看下面一个代码.

        Student student1 = new Student("小明", 95);
        Student student2 = new Student("小明", 95);
        if (student1 == student2) {
            System.out.printf("相等");
        } else {
            System.out.println("不相等");
        }

这段代码中我们创建了包含实例相同的两个对象,都是小明,95分.在运行之前我们也许会想它是相同的,但实则不然,结果为不相等.下面我们再提供一段相似的代码.

        Student student1 = new Student("小明", 95);
        Student student2 = student1;
        if (student1 == student2) {
            System.out.println("相等");
        } else {
            System.out.println("不相等");
        }

这段代码的结果为相等.为什么?
第一段代码中我们 new 了两个对象,但其实 == 在比较对象时,比较的是对象的身份(地址),每新建一个对象就会开辟一块内存, student1引用一个对象,而 student2 也引用一个内容一样但是地址不同的对象.

equals

上面提到了 == 的应用场景,但是我们所需要的是比较两个不同对象的内容是否相等,这里则需要对类中的 equals 方法进行覆写,来针对对象的特定实例域来进行比较,判断他们是否相等.

public class Student {
    public String name;
    public int score;
    
    public Student(String name, int score) {
        this.name = name;
        this.score = score;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (this.getClass() != obj.getClass()) {
            return false;
        }
        Student other = (Student)obj;
        return this.score == other.score
                && this.name.equals(other.name);
    }
}

equals 必须要比较的几点:

  1. 如果引用了同一个对象,返回 true
  2. 如果传入参数为 null,由于调用者不可能为 null,返回 false
  3. 如果这两个对象的类型不一样(getClass()可以获得对象的类型),返回false
  4. 最后要完成两个对象实例域的比较,这里比较成绩和姓名是否相同,(因为姓名是 String 类型,所以需要使用String类型的 equals 来进行比较,这里的equals 和我们覆写的equals 方法有所区别),返回 true,否则返回 false.
    下面我们创建两个实例相同的对象和一个不同的对象来进行比较.
Student student1 = new Student("小明", 98);
Student student2 = new Student("小明", 98);
Student student3 = new Student("小红", 95);

System.out.println(student1.equals(student2));
System.out.println(student1.equals(student3));

输出结果为

true
false

二. 针对对象值大于小于和等于的比较(自然顺序)

在比较了是否相等以后,我们也需要对学生的成绩来进行排名,但是每次新建的一个对象都是由姓名和得分这两个实例域构成的,所以我们需要在学生这个类中实现 Comparable 接口,来覆写该接口中的 compareTo 方法.这里我们要让学生类实现这个接口,并且覆写接口中的方法.

class Student implements Comparable<Student>{
    public String name;
    public int score;


    public Student(String name, int score) {
        this.name = name;
        this.score = score;
    }

    @Override
    public int compareTo(Student o) {
        if (o == null) {
            //这里设定任何对象都是大于null的
            return 1;
        }
        return this.score - o.score;
    }
}

观察这个覆写的 compareTo 方法,这里规定如果传进来的对象参数是 null , 则说明调用该方法的对象大于对象o.两个对象的分数实例域进行比较,如果调用方法的对象成绩大于被比较对象o,则返回正数,反之就返回一个负数,相等就返回0.
下面我们来对这个覆写方法制定的规则进行验证.

Student student1 = new Student("小明", 98);
Student student2 = new Student("小红", 95);
if (student1.compareTo(student2) > 0) {
    System.out.println("student1的分数比student2的分数高" );
} else if (student1.compareTo(student2) < 0) {
    System.out.println("student2的分数比student1的分数高" );
} else {
    System.out.println("student1的分数与student2的分数相等");
}

这段代码的输出结果为 student1的分数比student2的分数高.使用这样一个覆写 Comparable 接口的 compareTo 方法,能够很方便的让我们针对对象特定实例域来比较对象的大小.

三. 针对对象值大于小于和等于的比较(比较器)

刚才我们覆写的方法比较方式为一个一个对象引用调用方法,与方法传进来的参数进行比较.但如果我们想要使用方法来对两个传入的对象参数进行比较呢?
这时我们可以再创建一个类来做比较器,同时这个类要实现 Comparator 对象,再在这个比较器类中覆写 compare 方法,这个方法的参数是两个,再将内部的大小规则进行设定,就可以实现我们想要的效果.

public class ScoreComparator implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        if (o1 == o2) {
            return 0;
        }
        if (o1 == null) {
            return -1;
        }
        if (o2 == null) {
            return 1;
        }
        return o1.score - o2.score;
    }
}

这个覆写方法中传入了两个引用参数,相等就返回0, o1 的分数高就返回正数,反之返回负数.
下面来对这个覆写方法进行测试,我们还是使用刚才创建出来的两个学生对象为例来进行比较.

Student student1 = new Student("小明", 98);
Student student2 = new Student("小红", 95);
//创建比较器对象用来调用compare方法
ScoreComparator scoreComparator = new ScoreComparator();

if (scoreComparator.compare(student1,student2) > 0) {
    System.out.println("student1的分数比student2的分数高" );
} else if (scoreComparator.compare(student1,student2) < 0) {
    System.out.println("student2的分数比student1的分数高" );
} else {
    System.out.println("student1的分数与student2的分数相等");
}

这段代码运行的结果和刚才一样,都是student1的分数比student2的分数高,符合我们制定的比较规则.由于我们需要调用这个方法,所以要先创建一个比较器的类,这个类中覆写的 compare 方法也是针对 Student 学生类的分数来进行比较的,在使用的时候必须要创建一个比较器对象才能调用 compare 方法.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java中对象比较的三种方式 的相关文章

  • Java接口详解

    一 static静态关键字 定义变量不加static关键字 每个对象单独保存一个变量 定义变量加static关键字 静态变量 类变量 共享变量 public static 数据类型 变量名 所有对象会共享该变量 如果一个变量 静态变量 类变
  • instanceof,isInstance,isAssignableFrom的区别,以及isAssignableFrom()详解

    一 isAssignableFrom详解 这个方法我觉得是不好理解 感觉命名不对劲 不知道是不是错觉 Class类的isAssignableFrom Class cls 方法 如果调用这个方法的class或接口 与 参数cls表示的类或接口
  • JAVA-面向对象

    面向对象编程与面向过程编程只是一种在思维方式上的划分 面向过程是以分步骤的方式解决问题 而面向对象是以分步骤的方式解决问题 面向对象的三大特性是 封装 继承 多态 封装 就是将客观事物封装成抽象的类 抽象类可以将自己的数据和方法只让自己信任
  • Java异常(超详细!)

    1 什么是异常 java提供异常处理机制有什么用 什么是异常 程序执行过程中的不正常情况 异常的作用 增强程序的 健壮性 eg public class ExceptionTest01 public static void main Str
  • eclipse上配置JavaFX完整教程

    1 选择菜单栏Help中的Install New Software 2 点击Add添加安装JavaFx环境 name e fx clipse Location http download eclipse org efxclipse upda
  • Java--Map和HashMap基础

    一 Map常用方法 1 Map集合在 java util Map 包下 Map集合以键值对 key和value 的方式存储数据 key和value都是引用数据类型 都是存储对象的内存地址 2 Map接口中常用方法 V put K key V
  • JAVA接收JSON中的数组

    入参数据示例 respCode 0000 respMsg 请求成功 bizSeqNo 22022120001184432418054888526616 transTime 20220221180548 success true tokenA
  • Java-进制转换

    常用的进制转换 十进制转二进制 二进制转十进制 十进制转八进制 八进制转十进制 十进制转十六进制 十六进制转十进制 如果二 八 十六之间想转换可以通过十进制做中间者 import java util Scanner import java
  • Java——多线程使用详解

    多线程 多线程就是同时执行多个应用程序 需要硬件的支持 同时执行 不是某个时间段同时 cpu切换的比较快 所有用户会感觉是在同时运行 并发与并行 并行 parallel 指在同一时刻 有多条指令在多个处理器上同时执行 并行必须借助于多核cp
  • TCP通信发送和接收数据(Socket、ServerSocket)、TCP通信案例

    目录 TCP TCP发送接收数据 发送数据 Socket 接收数据 ServerSocket TCP通信案例1 TCP接收数据后给出反馈案例2 TCP接收数据后给出反馈案例3 TCP接收数据后给出反馈案例4 TCP 概述 TCP通信协议是一
  • Java的Properties属性集、获取项目路径的3种方式(干货满满)

    属性集介绍 集合家族中有个成员java util Properties 它继承于Hashtable Properties是使用键值结构存储数据的 但它最大的特点是具有持久化功能 持久化 内存 gt 硬盘 持久化的过程必须依赖于IO流 对IO
  • java中的异常

    异常 什么是异常 运行时异常和编译时异常 编译时异常 运行时异常 异常处理及其语法 异常的产生及处理 try catch语句 finally语句 抛出异常 throws关键字 throw关键字 自定义异常类 什么是异常 java中的异常是指
  • Java语言基础

    01 01 计算机基础知识 计算机概述 了解 A 什么是计算机 计算机在生活中的应用举例 计算机 Computer 全称 电子计算机 俗称电脑 是一种能够按照程序运行 自动 高速处理海量数据的现代化智能电子设备 由硬件和软件所组成 没有安装
  • Java多态

    关于引用的进一步理解 交换值 因为Java方法在传递参数的时候都是值传递 那么如何通过方法实现2个数的值交换 明确 在传引用的时候 到底拿引用干了个啥 class Value public int a public class Test p
  • Tank大战游戏模拟(java版)

    Java小项目 坦克大战 1 任务分析 玩家进入游戏 通过操纵坦克来守卫基地 摧毁全部敌方坦克来取得胜利 如果基地被摧毁 或者玩家坦克被摧毁 则判定游戏失败 2 具体分析 图形用户界面使用GUI技术实现 游戏中坦克的方向转动可以通过四种不同
  • 树型结构——二叉数

    之前就说过我们的数据结构分为两种 分别是线性结构和非线性结构 我们今天要学的第一种线性结构就是树型结构 1 树型结构 树型结构并非我们熟悉的重点 所以在这里只做了解 概念 树是一种非线性的数据结构 它是由n n gt 0 个有限结点组成一个
  • java虚拟机+分隔符

    java 入门 java 虚拟机 1 java虚拟机的平台可移植性 只要将java虚拟机安装于不同平台 我们编译的 class 文件就可以运行 2 jdk java开发 3 jre java运行时环境 jdk jre 下载安装后必须在环境变
  • private static final Long serialVersionUID= 1L详解

    我们知道在对数据进行传输时 需要将其进行序列化 在Java中实现序列化的方式也很简单 可以直接通过实现Serializable接口 但是我们经常也会看到下面接这一行代码 private static final Long serialVer
  • Java之单元测试(JUnit单元测试框架)

    一 概述 单元测试就是针对最小的功能单元编写测试代码 Java程序最小的功能单元是方法 所以单元测试就是针对Java方法的测试 进而检查方法的正确性 常规测试有什么问题 只有一个main方法 如果一个方法的测试失败了 其他方法会受到影响 无
  • java I/0操作 FileWriter类

    package filewriter p1 import java io FileWriter import java io IOException public class FileWriterDemo 获取当前系统的换行符 获取指定键指

随机推荐

  • 他98年的,我玩不过他...

    现在的小年轻真的卷得过分了 前段时间我们公司来了个98年的 工作没两年 跳槽到我们公司起薪18K 都快接近我了 后来才知道人家是个卷王 从早干到晚就差搬张床到工位睡觉了 最近和他聊了一次天 原来这位小老弟家里条件不太好 一大家子指望他一个人
  • Java 责任链模式

    责任链模式 一 什么是责任链模式 二 责任链模式的优势和劣势 2 1 优势 2 2 劣势 三 示例 一 什么是责任链模式 责任链模式定义 为了避免请求发送者与多个请求处理者耦合在一起 于是将所有请求的处理者通过前一对象记住其下一个对象的引用
  • YOLOv5+deepsort实现目标追踪。(附有各种错误解决办法)

    一 YOLOv5算法相关配置 这里如果是自己只想跑一跑YOLOV5的话 可以参考本章节 只想跑通YOLOv5 deepsort的看官移步到下一章节 1 1 yolov5下载 yolov5源码在github下载地址上或者Gitee上面都有 需
  • Critical dependency: the request of a dependency is an expression(import)

    定位到vue文件问题所在位置 export default created 告警所在 import md file then moduleFile gt catch err gt 原因 webpack 版本问题 webpack4中动态imp
  • 小程序中轮播图u-swiper图片无法显示问题

    问题 uview官网中 指定的图片路径字段为image 完全按照uview写轮播图却无法正常显示 解决方法 1 把image字段改成url字段 2 给u swiper加上 keyName image 最后找到了总结原因 npm下载的uvie
  • 【Spring源码】createBeanInstance()

    目录 创建实例 createBeanInstance 有参构造 autowireConstructor 无参构造 instantiateBean 实例化策略 instantiate createBeanInstance英文版 autowir
  • 你能写一个AIGC的python程序

    当然 我可以为您编写一个使用 Python 编写的 AIGC 程序 AIGC Artificial Intelligence Game Competition 是一种人工智能竞赛 其中参赛者需要编写人工智能程序 让其在模拟或真实游戏中进行操
  • linux服务器端启动NFS报“Job for nfs-server.service canceled.”的解决办法

    linux服务器端启动NFS报 Job for nfs server service canceled 的解决办法 网上百度了好久都没找到这个报错的原因 白嫖失败 打开linux的系统日志 tail f var log messages 再
  • CppUnit测试框架入门

    测试驱动开发 TDD 是以测试作为开发过程的中心 它坚持 在编写实际代码之前 先写好基于产品代码的测试代码 开发过程的目标就是首先使测试能够通过 然后再优化设计结构 测试驱动开发式是极限编程的重要组成部分 XUnit 一个基于测试驱动开发的
  • Spring Boot学习(一)之Controller的使用

    Controller 处理http请求 RestController RestController注解相当于 ResponseBody Controller合在一起的作用 Spring4之后新加入的注解 原来返回json需要 Respons
  • Pydantic系列之Model

    Model类 Python泛型类 TypeVar 是一个泛型类型变量 使用 bound 参数来限制所生成的类型的继承关系 from typing import Generic TypeVar from pydantic import Bas
  • Windows使用cmake编译dll

    目录 工具 注意事项 工具 CMake MinGW CMake工具负责将CMakeLists txt配置文件转换成相关的MakeFile脚本 本身并不参与编译 而是使用MinGW工具进行编译 在Linux系统使用CMake编译需要执行以下命
  • HashMap 面试题 11 问,看这篇就够了

    1 请你说说 HashMap 的数据结构有什么区别 jdk1 7 采用的是数组 链表结构 在 jdk1 8 采用数组 链表 红黑树的结构 2 上面说到 jdk1 8 之后增加了红黑树 什么 情况下转红黑树 什么情况下又转链表的 1 当链表的
  • 错误隐藏学习手记(三)

    帧内错误隐藏算法集合 1 空间加权像素平均算法 加权像素平均插值算法 P0就是丢失的宏块 灰色的是最近的像素点 2 方向插值 1 边缘检测及梯度计算 使用Sobel算子 计算的是Sx和Sy 水平边缘和垂直边缘 下图中 a b c d是缺失的
  • android:configChanges属性总结

    http blog csdn net zhaokaiqiang1992 article details 19921703 android中的组件Activity在manifest xml文件中可以指定参数android ConfigChan
  • 查看aspx文件安装什么服务器,aspx文件怎么打开?手把手教你怎么打开aspx文件

    原标题 aspx文件怎么打开 手把手教你怎么打开aspx文件 在电脑里面 有许多不同格式的文件 而不同文件的打开方法也不一样 比如最近就有位朋友看见了一个aspx文件 不知道怎么打开 其实 打开aspx文件很简单 只要右键 aspx文件 选
  • 微信小程序退出重新进入时跳转特定页面

    微信小程序退出时会记录当前页面的状态 短时间内再次进入会显示退出前的状态 解决方案 在app js文件中添加onHide方法 onHide方法监听小程序切后台 在app js文件中使用会在每次程序退出时调用 onLaunch functio
  • php 实现抽奖功能

    记录借载 核心算法
  • 华为ipd产品开发流程_IPD模式下的产品开发流程

    IPD产品开发流程体系 IPD产品开发流程体系来源于美国PRTM公司的 产品生命周期优化法 该体系集成了多个迄今为止最好的产品开发实践方法 也就是其来源于实践活动 反过来去指导实践 据PRTM公司统计 通过成功实施IPD 产品投入市场时间缩
  • Java中对象比较的三种方式

    一 针对对象值是否相等的比较 和 equals 的区别 当我们提到比较值的时候 大多数人都会想到 因为在一般情况下 人们对于比较的概念中 数字比较的应用场景出现频率是最多的 首先我们创建一个类 之后新建这个类的对象来进行比较验证 class