Java中哪些很容易出现的坑

文章目录

    • 1空指针
    • 2小数的计算
    • 3包装类型
    • 4Java8 Stream
    • 5日期格式化

先来一个简单一点,就从空指针开始吧

1空指针

//多级调用空指针userService.getUser("张三").getUserInfo().getUserName();
//例如getUser("张三")、getUserInfo()都可能出现null//equals空指针,当我们的str通过某个方法获取(或者传参),而这个方法可能返回null,其代码等价于如下
String str = null; //xxxService.doSomeThing();
if(str.equals("张三")){System.out.println("我是张三");
}//集合遍历,当我们的list通过某个方法获取(或者传参),而这个方法可能返回null,其代码等价于如下
List<User> list = null; //xxxService.doSomeThing();
for (User user : list) {System.out.println(user);
}//包装类型的空指针,如果使用包装类型,包装类型是可能为null,对其进行算术操作,会出控制
Integer num = null;
System.out.println(num + 1);

2小数的计算

如下图所示,我们挑选了几个数字,做了加减乘除的操作,代码很简单,结果很意外。
在这里插入图片描述
这样的代码很容易就不经意间写出来了,然后BUG就产生了。因此,如果你的代码中有用到包含小数进行加减乘除的操作,及其容易出现意想不到的结果,得到的数会很接近你的目标小数,但是不是你的目标数,如果此时做大小等于判断以及高精度,就很容易出现BUG了。

其主要原因主要有如下

  1. 二进制表示不精确:计算机使用二进制表示浮点数,而十进制的小数无法精确表示为有限长度的二进制小数。某些十进制小数在二进制表示中是无限循环的,因此在转换过程中会有截断或舍入误差。
  2. 浮点数运算规则:浮点数的加法、减法、乘法和除法运算都遵循IEEE 754标准的规则。这些规则对于某些十进制小数可能会产生舍入误差,尤其是在进行多次运算时。
  3. 存储空间限制:浮点数通常使用有限的位数来表示,例如float类型使用32位,double类型使用64位。这种有限的存储空间限制了浮点数的精度,因此在进行计算时可能会丢失一些细微的精度。

解决办法

  1. 需要精确的计算:提高精度,使用高精度的计算,可以使用BigDecimal类,它提供了高精度的十进制计算。使用BigDecimal可以增加浮点数的精度(不能完全消除),但同时也需要更多的计算和内存开销。因此,根据具体需求,需要权衡精度和性能之间的取舍。一般适用于比较严谨或者数值比较大的场景,例如金钱的计算,例如某公司流上千亿流水,某银行的存款有百万亿,这种情况下,即使是亿分之1的精度,每次计算那也是会丢失几百上千,甚至上万的丢失。
  2. 不需要精确的计算:降低精度,保留低精度的结果进行比较,忽略细小的进度差距。例如格式化输出、四舍五入等
//格式化
double result = 0.1 * 0.2;
System.out.println(String.format("%.2f", result)); // 输出:0.02,保留两位小数//四舍五入  乘法结果乘以100后使用Math.round()进行四舍五入,然后除以100.0来保留两位小数
double result = 0.1 * 0.2;
System.out.println(String.format("%.2f", result)); // 输出:0.02,保留两位小数//四舍五入,setScale()方法设置保留小数的位数,并指定舍入模式为RoundingMode.HALF_UP进行四舍五入
BigDecimal num1 = new BigDecimal("0.1");
BigDecimal num2 = new BigDecimal("0.2");
BigDecimal result = num1.multiply(num2).setScale(2, RoundingMode.HALF_UP);
System.out.println(result); // 输出:0.02,保留两位小数

备注:BigDecimal的正确使用,如下的三个例子中,可以发现第一种实现方式一样存在精度问题,这是为什么勒?
在这里插入图片描述
我们查看valueOf的源码发现,其首先将浮点数转换成字符串,也就是上面我们的第三种方式
在这里插入图片描述
究其原因,浮点数类型(如 double)是基于二进制表示的,而某些十进制数无法精确表示为有限长度的二进制小数,new BigDecimal(0.1)实际上是将 double 类型的值转换为 BigDecimal,而new BigDecimal(“0.1”)会将传入的参数作为字符串进行精确表示。
当我们使用浮点数参数,代码扫描工具会提示,使用valueOf替换,而使用字符串参数则不会提示。
在这里插入图片描述

3包装类型

在java中,我们看一下基本数据类型有8种。

整数类型:
byte8位有符号整数,取值范围为-128127short16位有符号整数,取值范围为-32,76832,767int32位有符号整数,取值范围为约-21亿到21亿。
long64位有符号整数,取值范围为约-922万亿亿到922万亿亿。浮点数类型:
float32IEEE 754单精度浮点数,取值范围约为±1.4e-45到±3.4e+38,精度约为6-7位小数。
double64IEEE 754双精度浮点数,取值范围约为±4.9e-324到±1.8e+308,精度约为15位小数。字符类型:
char16Unicode字符,表示单个字符。布尔类型:
boolean:表示真或假的值,只有两个取值:truefalse
每个基本数据类型都有对应的包装类,用于提供额外的功能和操作。以下是基本数据类型及其对应的包装类:
byte:对应的包装类是 Byte
short:对应的包装类是 Short
int:对应的包装类是 Integer
long:对应的包装类是 Long
float:对应的包装类是 Float
double:对应的包装类是 Double
char:对应的包装类是 Character
boolean:对应的包装类是 Boolean

在这里,我们以Integer为例说明,先看下面的代码,如果你以前不知道这个坑,那么铁定会有点无语
在这里插入图片描述
1基本类型有默认值

现象:num0_1和num0_2都没有进行赋值,直接打印值时,基本类型的num0_1为0,包装类型的num0_2为null,
原因:基本类型会有一个默认值,而包装类型则没有默认值。
建议:使用基本类型时,避免使用默认值。使用包装类型时,赋予初始值,防止空指针。
例如:使用int表示状态:0表示成功, 1表示失败,此时有个问题,不管是设置成功状态,还是状态没有设置值,其值都是0, 因此可以改为,用1表示成功,2表示失败

2==比较

现象:num1和num2都是127,使用==比较,结果为true,而num5和num6都是128,结果却为false
原因:使用 == 运算符比较两个对象时,会比较它们的引用是否指向同一个对象。这意味着如果两个包装类型对象的引用指向相同的对象,则 == 操作符返回 true,否则返回 false。

对于整数类型的包装类 Byte、Short、Integer 和 Long,Java提供了一个对象缓存池(Object Pool),范围是 -128 到 127。
这意味着当创建一个值在这个范围内的整数类型包装类对象时,会从缓存池中获取已存在的对象,而不是创建新的对象。
当 num1 和 num2 的值都为 127 时,它们在范围内,并且 Byte、Short、Integer 和 Long 类型的对象在范围内的情况下会被缓存。因此,使用 == 比较时,它们引用的是相同的对象,所以结果为 true。

当 num5 和 num6 的值都为 128 时,它们超出了缓存池的范围。在这种情况下,每次创建包装类型对象时,都会创建一个新的对象。因此,虽然它们的值相同,但它们引用的是不同的对象,所以使用 == 比较时结果为 false。

建议:使用包装类提供的 equals() 方法,它会比较对象的值而不仅仅是引用

3构造方法
现象:num3和num4也是127,也在缓存范围值内,==比较结果是false
原因:Integer的构造方法中,并没有使用缓存,缓存是在valueOf方法中使用的,因此是用new Integer(127) 并不会用缓存
在这里插入图片描述
建议:使用包装类提供的 equals() 方法,它会比较对象的值而不仅仅是引用
我的IDE环境中,安装了一些代码扫描插件,我们可以看到,此时提示我们,String和包装类型的比较应该使用equals()
在这里插入图片描述

4Java8 Stream

Java8中的Stream可以简化集合数据的处理和操作,最常见的排序,过滤,去重等,这里我们以排序为例进行操作

filter(Predicate):根据指定条件过滤流中的元素。
map(Function):将流中的每个元素映射到另一个元素。
sorted():对流中的元素进行排序。
distinct():去除流中的重复元素。
limit(n):限制流中元素的数量为 n。
skip(n):跳过流中的前 n 个元素。

我们按照年龄进行排序后,然后取第一个元素,将第一个用户的年龄修改为100,我们发现,原始数据也被修改了
在这里插入图片描述
原因:过滤后的集合中,保存的是对象的引用,该引用只有一份数据。也就是说,只要有一个地方,把该引用对象的成员变量的值,做修改了,其他地方也会同步修改。

5日期格式化

正确的日期格式化:yyyy-MM-dd
错误的日期格式化:YYYY-MM-dd
我们分别使用SimpleDateFormat和java8中的DateTimeFormatter来格式化,有些时间格式化是正确的,有些时间格式化又是错误的。
先看一个时间,2023年12月30日(格式正确的时间)
在这里插入图片描述

在看一个时间,2023年12月31日(格式错误的时间)
在这里插入图片描述
因此,如果你使用的日期格式如果为YYYY-MM-dd,那就是有时时间对,有时时间不对,够你排查喝一壶了

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

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

相关文章

【RT-DETR有效改进】 多维度注意力机制 | TripletAttention三重立体特征选择模块

一、本文介绍 本文给大家带来的改进是Triplet Attention三重注意力机制。这个机制&#xff0c;它通过三个不同的视角来分析输入的数据&#xff0c;就好比三个人从不同的角度来观察同一幅画&#xff0c;然后共同决定哪些部分最值得注意。三重注意力机制的主要思想是在网络中引入…

从零开始手写mmo游戏从框架到爆炸(十六)— 客户端指定回调路由与登录

导航&#xff1a;从零开始手写mmo游戏从框架到爆炸&#xff08;零&#xff09;—— 导航-CSDN博客 我们这次来把注册、登录、选择英雄&#xff0c;进入主页-选择地图的功能完善。 在这之前&#xff0c;我们还要解决一个问题&#xff0c;就是服务端往客户端发消息的路由问题…

【漏洞复现】H3C 路由器多系列信息泄露漏洞

Nx01 产品简介 H3C路由器是一款高性能的路由器产品&#xff0c;具有稳定的性能和丰富的功能。它采用了先进的路由技术和安全机制&#xff0c;可以满足不同用户的需求&#xff0c;广泛应用于企业、运营商和数据中心等领域。 Nx02 漏洞描述 H3C路由器多系列存在信息泄露漏洞&…

网络爬虫基础(上)

1. 爬虫的基本原理 爬虫就是在网页上爬行的蜘蛛&#xff0c;每爬到一个节点就能够访问该网页的信息&#xff0c;所以又称为网络蜘蛛&#xff1b; 网络爬虫就是自动化从网页上获取信息、提取信息和保存信息的过程&#xff1b; 2. URL的组成部分 URL全称为Uniform Resource L…

Oracle 如何提高空间使用率?

一&#xff0c;行迁移和行链接。 oracle尽量保证一行的数据能够放在同一个数据块当中&#xff0c;有的时候行会发生行迁移和行链接。 行链接 &#xff1a;有一个列的字段是大对象&#xff08;long&#xff0c;longlong&#xff09;一行占的数据一整个块都放不下&#xff0c;则…

07 Redis之持久化(RDB+AOF)

4 Redis持久化 Redis 是一个内存数据库&#xff0c;然而内存中的数据是不持久的&#xff0c;若主机宕机或 Redis 关机重启&#xff0c;则内存中的数据全部丢失。 当然&#xff0c;这是不允许的。Redis 具有持久化功能&#xff0c;其会按照设置以快照或操作日志的形式将数据持…

Leetcode刷题笔记题解(C++):83. 删除排序链表中的重复元素

思路&#xff1a;链表相关的问题建议就是画图去解决&#xff0c;虽然理解起来很容易&#xff0c;但就是写代码写不出来有时候&#xff0c;依次去遍历第二节点如果与前一个节点相等则跳过&#xff0c;不相等则遍历第三个节点 /*** Definition for singly-linked list.* struct …

uniapp不同平台获取文件内容以及base64编码特征

前言 文件图片上传&#xff0c;客户端预览是很正常的需求&#xff0c;获取文件的md5特征码也是很正常的&#xff0c;那么&#xff0c;在uniapp中三种环境&#xff0c;h5, 小程序以及 app环境下&#xff0c;如何实现的&#xff1f; 参考&#xff1a; 如何在uniapp中读取文件Arr…

Https证书续签-acme.sh-腾讯云之DnsPod

ename 域名切换到 DnsPod 上面解析 可以先看下之前的 acme.sh 介绍文章然后再来次补充更多。 之前说过了 acme.sh 在阿里云下的使用。 这里做个后续补充 之前的域名是在 ename 上的 &#xff0c;为了自动续签切换到 DnsPod 上面解析 注意事项 可以把原来 ename 上的解析先导出…

多端开发围炉夜话

文章目录 一、多端开发 一、多端开发 uni-app 官网 UNI-APP中的UI框架&#xff1a;介绍常用的UI框架及其特点 uView UIVant WeappColor UIMint UI

python 与 neo4j 交互(py2neo 使用)

参考自&#xff1a;neo4j的python.py2neo操作入门 官方文档&#xff1a;The Py2neo Handbook — py2neo 2021.1 安装&#xff1a;pip install py2neo -i https://pypi.tuna.tsinghua.edu.cn/simple 1 节点 / 关系 / 属性 / 路径 节点(Node)和关系(relationship)是构成图的基础…

Android 7.0以上charles无法抓取部分https包问题

首先保证配置一切正确 手机通过访问chls.pro/ssl下载.pem证书&#xff0c;如无法安装&#xff0c;在文件管理器中将后缀名改为.crt 在设置中安装该证书 Charles-Proxy - SSL Proxying Setting - Include 添加需要抓包的URL:443即可 以上基本配置结束后&#xff0c;看下代码 代…

Java+SpringBoot:滑雪场管理的技术革新

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

Linux挂载磁盘和磁盘分区及设置开机自动挂载_亲测成功

Linux挂载磁盘和磁盘分区及设置开机自动挂载_亲测成功 Linux下磁盘分区命令主要由两个&#xff1a; fdisk &#xff1a;最大支持不超过2T,MBR分区&#xff1b;parted &#xff1a;支持GPT&#xff0c;适用于大容量分区&#xff1b; 如果挂载磁盘超过2T,请使用GPT分区,不然会…

探索水下低光照图像检测性能,基于DETR(DEtection TRansformer)模型开发构建海底生物检测识别分析系统

海底这类特殊数据场景下的检测模型开发相对来说比较少&#xff0c;在前面的博文中也有一些涉及&#xff0c;感兴趣的话可以自行移步阅读即可&#xff1a; 《尝试探索水下目标检测&#xff0c;基于yolov5轻量级系列模型n/s/m开发构建海底生物检测系统》 《基于YOLOv5C3CBAMCBA…

搜维尔科技:OptiTrack探索人类与技术之间关系的开创性表演

另一种蓝色通过 OptiTrack 释放创造力 总部位于荷兰的当代舞蹈团因其探索人类与技术之间关系的开创性表演而受到广泛赞誉。该公司由富有远见的编舞家大卫米登多普创立&#xff0c;不仅利用技术作为探索的主题&#xff0c;而且将其作为表达故事的动态工具。 “我一直对文化与…

超平面介绍

超平面公式 (1) 超平面是指n维线性空间中维度为n-1的子空间。它可以把线性空间分割成不相交的两部分。比如二维空间中&#xff0c;一条直线是一维的&#xff0c;它把平面分成了两部分&#xff1b;三维空间中&#xff0c;一个平面是二维的&#xff0c;它把空间分成了两部分。(2…

五种多目标优化算法(MOAHA、MOGWO、NSWOA、MOPSO、NSGA2)性能对比,包含6种评价指标,9个测试函数(提供MATLAB代码)

一、5种多目标优化算法简介 1.1MOAHA 1.2MOGWO 1.3NSWOA 1.4MOPSO 1.5NSGA2 二、5种多目标优化算法性能对比 为了测试5种算法的性能将其求解9个多目标测试函数&#xff08;zdt1、zdt2 、zdt3、 zdt4、 zdt6 、Schaffer、 Kursawe 、Viennet2、 Viennet3&#xff09;&#xff…

iOS整理 - 关于直播 - 搭建服务端

前言 其实本人一直都想自己简单做一套直播&#xff08;包括移动端和服务端&#xff09;的开发测试&#xff0c;但是之前一直做得比较迷茫。最近偶然间在来了灵感&#xff0c;瞬间解除了我很多疑惑。我会分享出来&#xff0c;希望大家一起研究下。稍后&#xff0c;我完整做好了…

python在flask中的请求数据“无限流”

文章目录 一、问题描述二、解决方案 一、问题描述 在flask请求中&#xff0c;有个需求是让调用方一直调接口&#xff0c;并立马返回&#xff0c;而接口方缓存请求&#xff0c;依次执行。 二、解决方案 from flask import Flask, request, jsonify from queue import Queue i…