项目实战典型案例9——数据类型不一致导致equals判断为false

简介: 项目实战典型案例9——数据类型不一致导致equals判断为false

数据类型不一致导致equals判断为false

一:背景介绍

对课程id和班级id分别进行判断,如果分别一致就更新该课程班班级信息,拖过不一致就插入新的一条数据。由于这里使用将两个类型不一致的变量使用equals进行比较,结果肯定为false,导致会插入相同课程班级的数据,从而导致数据混乱。



二:思路&方案

上面出现的问题主要原因是对于equals的使用有误,不清楚如何使用equals导致出现的问题。下面让我们来看一下如何正确的使用equals以及使用equals的一些技巧。

  1. 查看一下equals方法的源码,equals是Object类中的方法,可以从Object类中看出equals方法比较的是对象的地址。
public boolean equals(Object obj) {
        return this == obj;
    }
  1. 以包装类Integer为例,是对equals进行了重写,我们可以看出比较的是内容。其实对于其他基本类型的包装类型来说equals都是比较的内容。
public boolean equals(Object obj) {
    //如果指定对象是Integer类型,则继续
        if (obj instanceof Integer) {
          //则先将该对象强转为Integer对象,比较内容
            return this.value == (Integer)obj;
        } else {
            return false;
        }
    }

结论

  1. 如果equals方法没有被重写,那么比较的是两个对象的地址
  2. 如果equals方法被重写,那么走的是重写的逻辑。
  3. 基本类型的包装类型都对equals方法进行了重写,比较的都是值,而不是地址。

三:equals的使用技巧

主要依据阿里规约中对于equals使用的注意事项

基本数据类型与其对应的包装类

基本数据类型 对应的包装类型
byte(整数类型) Byte
short(整数类型) Short
int (整数类型) Integer
long(整数类型) Long
float(浮点类型) Float
double(浮点类型) Double
char(字符类型) Character
boolean Boolean

1.Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。
2.所有整型包装类对象之间值的比较,全部使用 equals 方法比较。

说明:对于 Integer var = ? 在 -128 至 127 之间的赋值,Integer 对象是在 IntegerCache.cache 产生,会复用已有对象,这个区间内的 Integer 值可以直接使用 == 进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复

用已有对象,这是一个大坑,推荐使用 equals 方法进行判断。

public class Client {
    public static void main(String[] args) {
        Integer a =128;
        Integer b=128;
        Integer c=127;
        Integer d=127;
        System.out.println(a.equals(b));
        System.out.println(a==b);
        System.out.println(c==d);
    }


  1. 浮点数之间的等值判断,基本数据类型不能使用 == 进行比较,包装数据类型不能使用 equals
    进行判断。

    说明:浮点数采用“尾数+阶码”的编码方式,类似于科学计数法的“有效数字+指数”的表示方式。二进制无法精确表示大部分的十进制小数。
    可以使用BigDecimal来定义值,再进行浮点数的运算操作。
public static void main(String[] args) {
        BigDecimal a = new BigDecimal("1.0");
        BigDecimal b = new BigDecimal("0.9");
        BigDecimal c = new BigDecimal("0.8");
        BigDecimal x = a.subtract(b);
        BigDecimal y = b.subtract(c);
        if (x.compareTo(y) == 0) {
            System.out.println("true");
        }
    }


  1. BigDecimal 的等值比较应使用 compareTo() 方法,而不是 equals() 方法。
    说明:equals() 方法会比较值和精度(1.0 与 1.00 返回结果为 false),而 compareTo() 则会忽略精度。
目录
相关文章
Debian 官方源换为国内的源的操作方法
apt-get update 报错,采用更换源的方式解决问题。
56916 0
|
JavaScript Java Spring
springboot+vue 实现校园二手商城(毕业设计一)
这篇文章介绍了一个使用Spring Boot和Vue实现的校园二手商城系统的毕业设计,包括用户和商家的功能需求,如登录注册、订单管理、商品评价、联系客服等,以及项目依赖项的安装过程。
springboot+vue 实现校园二手商城(毕业设计一)
|
10月前
|
Java 调度 数据库
SpringBoot整合XXL-JOB【05】- 任务分片
在实际业务中,批量定时任务可能因上一批任务未完成而影响业务。为解决此问题,本文介绍如何使用Xxl-job对批量任务进行分片处理,通过分片广播形式调度集群机器并行执行任务,大幅提升执行效率。具体步骤包括环境准备、添加依赖和配置、声明实体类与查询类,以及改造业务逻辑实现分片查询。测试结果显示,分片处理将两千条数据的执行时间从30秒缩短至15秒,性能提升显著。
1192 13
SpringBoot整合XXL-JOB【05】-  任务分片
|
缓存 Java 开发工具
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存
三级缓存是Spring框架里,一个经典的技术点,它很好地解决了循环依赖的问题,也是很多面试中会被问到的问题,本文从源码入手,详细剖析Spring三级缓存的来龙去脉。
1300 24
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存
|
存储 安全 Java
Java 中 Vector 和 ArrayList 的详细对比
【8月更文挑战第23天】
246 2
|
存储 Java 关系型数据库
“代码界的魔法师:揭秘Micronaut框架下如何用测试驱动开发将简单图书管理系统变成性能怪兽!
【9月更文挑战第6天】Micronaut框架凭借其轻量级和高性能特性,在Java应用开发中备受青睐。本文通过一个图书管理系统的案例,介绍了在Micronaut下从单元测试到集成测试的全流程。首先,我们使用`@MicronautTest`注解编写了一个简单的`BookService`单元测试,验证添加图书功能;接着,通过集成测试验证了`BookService`与数据库的交互。整个过程展示了Micronaut强大的依赖注入和测试支持,使测试编写变得更加高效和简单。
256 4
|
自然语言处理 Java 开发者
简单了解下Spring中的各种Aware接口实现依赖注入
【8月更文挑战第21天】在Spring框架中,Aware接口系列是一种特殊的机制,它允许Bean在初始化过程中获取到Spring容器或容器中的特定资源,从而实现了更加灵活和强大的依赖注入方式。本文将围绕Spring中的各种Aware接口,详细探讨它们如何帮助开发者在工作和学习中更好地实现依赖注入。
400 0
|
XML JSON Java
spring,springBoot配置类型转化器Converter以及FastJsonHttpMessageConverter,StringHttpMessageConverter 使用
spring,springBoot配置类型转化器Converter以及FastJsonHttpMessageConverter,StringHttpMessageConverter 使用
1538 1
|
并行计算 Java 应用服务中间件
JUC并发编程超详细详解篇(一)
JUC并发编程超详细详解篇
2164 1
JUC并发编程超详细详解篇(一)
|
Java 测试技术 Spring
什么是循环依赖,如何解决?
在 Spring 应用中,循环依赖指的是两个或多个 Bean 之间相互引用,造成了一个环状的依赖关系。举例来说,如果 Bean A 依赖于 Bean B,同时 Bean B 也依赖于 Bean A,就形成了循环依赖。这种情况下,Spring 容器在创建这些 Bean 时会陷入无限循环,导致应用启动失败或者出现其他不可预测的问题。
851 1