Java基础概览和常用知识(七)
什么是自动装箱和自动拆箱,原理是什么?
自动装箱和自动拆箱是Java编程语言中的两个重要概念,它们涉及到基本数据类型与其对应包装类之间的自动转换。
一、定义
自动装箱:是指Java编译器在需要将基本数据类型转换为对应的包装类时,会自动进行转换的过程。例如,将int类型转换为Integer类型,将double类型转换为Double类型等。
自动拆箱:则是自动装箱的逆过程,即Java编译器在需要将包装类对象转换为对应的基本数据类型时,会自动进行转换。例如,将Integer类型转换为int类型,将Double类型转换为double类型等。
二、原理
自动装箱:当基本数据类型被赋值给一个包装类对象时,编译器会自动生成一个调用对应包装类构造函数的代码。这种转换是通过包装类的构造函数或静态工厂方法(例如Integer.valueOf(int i))实现的。
自动拆箱:当包装类对象被赋值给基本数据类型时,编译器会自动生成一个调用包装类的xxxValue()方法的代码,以获取基本数据类型的值。这种转换是通过包装类提供的xxxValue()方法实现的,其中xxx表示基本数据类型(如intValue、doubleValue等)。
三、例子
- 自动装箱:
int num = 5;
Integer numObj = num; // 自动装箱,编译器会将int类型的num自动转换为Integer类型的numObj
在这个例子中,编译器将int类型的num自动转换为Integer类型的numObj。
- 自动拆箱:
Integer numObj = 10;
int num = numObj; // 拆箱,编译器会将Integer类型的numObj自动转换为int类型的num
在这个例子中,编译器将Integer类型的numObj自动转换为int类型的num。
另外,自动装箱和拆箱在Java集合框架(如ArrayList)中尤为重要,因为这些框架只能存储对象而不能存储基本数据类型。例如:
ArrayList<Integer> list = new ArrayList<>();
list.add(10); // int 10 被自动装箱为 Integer 对象
int value = list.get(0); // Integer 对象被自动拆箱为 int 基本类型
在这个例子中,list.add(10)将int类型的10自动装箱为Integer对象,然后list.get(0)将Integer对象自动拆箱为int基本数据类型。
举例:
Integer i = 10; //装箱
int n = i; //拆箱
上面这两行代码对应的字节码为:
L1LINENUMBER 8 L1ALOAD 0BIPUSH 10INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;PUTFIELD AutoBoxTest.i : Ljava/lang/Integer;L2LINENUMBER 9 L2ALOAD 0ALOAD 0GETFIELD AutoBoxTest.i : Ljava/lang/Integer;INVOKEVIRTUAL java/lang/Integer.intValue ()IPUTFIELD AutoBoxTest.n : IRETURN
从字节码中,我们发现装箱其实就是调用了 包装类的valueOf()
方法,拆箱其实就是调用了 xxxValue()
方法。
因此,
Integer i = 10
等价于Integer i = Integer.valueOf(10)
int n = i
等价于int n = i.intValue()
;
注意:如果频繁拆装箱的话,也会严重影响系统的性能。我们应该尽量避免不必要的拆装箱操作。
private static long sum() {// 应该使用 long 而不是 LongLong sum = 0L;for (long i = 0; i <= Integer.MAX_VALUE; i++)sum += i;return sum;
}
总的来说,自动装箱和自动拆箱机制使得Java语言的基本数据类型与对象之间的转换变得更加简单和高效。然而,在使用时也需要注意其潜在的问题,如性能开销和可能的空指针异常等。因此,在编写代码时,应尽量避免在循环或大量计算中自动装箱,如果可能,手动进行装箱操作以减少不必要的开销。
什么浮点数运算的时候会有精度丢失的风险?
浮点数运算时会有精度丢失的风险,这主要源于浮点数在计算机中的表示方式及其运算特性。以下是对这一现象的详细解释:
一、浮点数的表示方式
二进制系统:计算机内部使用二进制系统来存储和处理数据。然而,许多十进制小数在转换为二进制时无法得到一个有限长度的循环小数或终止小数,例如十进制的0.1在二进制中就是无限循环小数。
IEEE 754标准:浮点数在计算机中通常采用IEEE 754标准进行表示,该标准定义了浮点数的编码格式,包括符号位、指数部分和尾数部分。其中,尾数的位数是有限的,这意味着浮点数只能精确地表示一定数量的小数位数。
二、精度丢失的原因
有限位数:由于浮点数的尾数位数有限,因此无法精确表示所有的十进制小数。当小数位数超过尾数的表示范围时,就会发生精度丢失。
舍入误差:在浮点数运算过程中,由于数值的内部表示不精确,运算结果也需要进行舍入处理以适应浮点数的存储格式。这种舍入误差会随着多次运算的累积而逐渐增大,最终导致精度丢失。
二进制与十进制的不匹配:由于二进制和十进制之间的不匹配,某些十进制小数在二进制中无法精确表示,这也会导致精度丢失。
三、精度丢失的影响
计算误差:精度丢失会导致计算结果与期望结果之间存在误差。这种误差在多次运算后会逐渐累积,最终影响结果的准确性。
比较问题:由于浮点数的精度问题,直接比较两个浮点数是否相等通常是不可靠的。即使两个浮点数的值在视觉上非常接近,它们在底层的二进制表示中也可能存在微小差异。
四、应对措施
使用BigDecimal类:在需要高精度计算的场景中,可以使用Java中的BigDecimal类来代替浮点数进行运算。BigDecimal类可以精确表示小数,并且允许开发者控制舍入模式,从而避免浮点数的精度问题。
引入误差容忍度:在比较两个浮点数时,可以引入误差容忍度(也称为epsilon),即允许两个浮点数的差值在某个很小的范围内视为相等。这样可以避免直接比较浮点数时产生的误差。
选择合适的数值类型:根据实际需求选择合适的数值类型,如float、double或BigDecimal。在可能的情况下,优先选择精度更高的数值类型以减少精度丢失的风险。
综上所述,浮点数运算时会有精度丢失的风险,这主要源于浮点数的表示方式和运算特性。为了降低这种风险,可以采取相应的应对措施来确保计算的准确性。
如何解决浮点数运算的精度丢失问题?
浮点数运算的精度丢失问题在计算机科学中是一个普遍存在的挑战,源于二进制无法精确表示某些十进制小数以及运算过程中的舍入误差。以下是一些解决浮点数运算精度丢失问题的方法:
一、使用整数进行计算
- 原理:
- 将浮点数转换为整数进行计算,可以避免浮点数表示不精确的问题。
- 通过放大或缩小数值的倍数(如乘以10的幂),将浮点数转换为整数进行计算,然后再将结果转换回浮点数。
function multiply(a, b) { const multiplier = 10000; // 选择一个合适的倍数,如10000 const intA = a * multiplier; const intB = b * multiplier; return (intA * intB) / (multiplier * multiplier);
}
二、使用toFixed()
方法
- 原理:
toFixed()
方法可以将浮点数四舍五入到指定的小数位数。- 需要注意的是,
toFixed()
返回的是一个字符串,需要使用parseFloat()
将其转换回数字。
const result = parseFloat((0.1 + 0.2).toFixed(10));
三、使用第三方库
- 原理:
- 有一些第三方库专门用于处理浮点数计算精度问题,如
decimal.js
、bignumber.js
等。 - 这些库提供了一系列方法来进行高精度的浮点数计算。
- 有一些第三方库专门用于处理浮点数计算精度问题,如
- 示例:
- 使用
decimal.js
库:
- 使用
import Decimal from 'decimal.js';
const a = new Decimal(0.1);
const b = new Decimal(0.2);
const result = a.plus(b).toNumber();
四、使用BigDecimal
类(Java)
- 原理:
- 在Java中,
BigDecimal
类可以精确表示小数,并且允许开发者控制舍入模式。 BigDecimal
提供了丰富的数学运算方法,可以避免浮点数的精度问题。
- 在Java中,
import java.math.BigDecimal;
public class BigDecimalExample { public static void main(String[] args) { BigDecimal a = new BigDecimal("0.1"); BigDecimal b = new BigDecimal("0.2"); BigDecimal sum = a.add(b); System.out.println(sum); // 输出: 0.3 }
}
五、引入误差容忍度(epsilon)
- 原理:
- 在比较两个浮点数时,由于它们在底层的二进制表示中可能存在微小差异,直接比较可能会导致错误的结果。
- 引入误差容忍度(epsilon),即允许两个浮点数的差值在某个很小的范围内视为相等。
double a = 0.1 + 0.2;
double b = 0.3;
double epsilon = 1e-10; // 容忍度
System.out.println(Math.abs(a - b) < epsilon); // 输出: true
六、使用整数表示货币值
- 原理:
- 在处理货币运算时,可以使用整数来表示货币值(如以分为单位表示货币值而不是以元),从而避免浮点数精度问题。
int priceInCents = 100; // 1.00元表示为100分
int quantity = 3;
int totalCostInCents = priceInCents * quantity;
System.out.println("总价:" + (totalCostInCents / 100.0) + " 元"); // 输出: 3.00 元
综上所述,解决浮点数运算精度丢失问题的方法有多种,可以根据具体场景和需求选择合适的方法。在实际应用中,应尽量避免在需要高精度计算的场景中使用浮点数,而是采用整数或其他高精度数据类型进行计算。
超过Long整型的数据应该如何表示?
基本数值类型都有一个表达范围,如果超过这个范围就会有数值溢出的风险。
在 Java 中,64 位 long 整型是最大的整数类型。
long l = Long.MAX_VALUE;
System.out.println(l + 1); // -9223372036854775808
System.out.println(l + 1 == Long.MIN_VALUE); // true
BigInteger
内部使用 int[]
数组来存储任意大小的整形数据。
相对于常规整数类型的运算来说,BigInteger
运算的效率会相对较低。
相关文章:
Java基础概览和常用知识(七)
什么是自动装箱和自动拆箱,原理是什么? 自动装箱和自动拆箱是Java编程语言中的两个重要概念,它们涉及到基本数据类型与其对应包装类之间的自动转换。 一、定义 自动装箱:是指Java编译器在需要将基本数据类型转换为对应的包装类…...

STL-string
STL的六大组件: string // string constructor #include <iostream> #include <string> using namespace std; int main() {// 构造std::string s0("Initial string");std::string s1; //nullptrstd::string s2("A character sequenc…...
数据库基础-学习版
目录 数据库巡检清理表空间高水位处理重建索引扩展字段异常恢复处置常见命令汇总 数据库巡检 数据库巡检的主要目的是确保数据库的健康状态、性能和安全,及时发现潜在的问题。 一 数据库状态检查 查看数据库列表:SHOW DATABASES; 检查当前数据库SELECT DATABASE(); 检查数据…...
【Gin】Gin框架介绍和使用
一、简单使用Gin框架搭建一个服务器 package mainimport ("github.com/gin-gonic/gin" )func main() {// 创建一个默认的路由引擎r : gin.Default()// GET 请求方法r.GET("/hello", func(c *gin.Context) {// c.JSON 返回的是JSON格式的数据c.JSON(200, g…...
AI大模型带来哪些创业机遇?
AI 大模型的快速发展带来了许多创新和创业机遇,涵盖了从行业应用到基础设施优化的方方面面。以下是一些具体的创业机会: 1、垂直行业应用 大模型可以根据不同行业的需求进行定制和优化,提供高度专业化的 AI 解决方案。 医疗领域:…...

[Linux] 层层深入理解文件系统——(3)磁盘组织存储的文件
标题:[Linux] 层层深入理解文件系统——(3)磁盘组织组织存储的文件 个人主页水墨不写bug 目录 一、磁盘中的文件 1)磁盘的物理结构 2)磁盘的CHS寻址法 3)磁盘的空间管理 二、磁盘如何组织存储文件 三…...
Apache Cordova学习计划
Apache Cordova(之前称为 PhoneGap): 1. PhoneGap的起源:2008年8月,PhoneGap在旧金山的iPhoneDevCamp上首次亮相,由Nitobe公司开发,目的是“为跨越Web技术和iPhone之间的鸿沟牵线搭桥”。 2. Ph…...
Unity学习日志-API
Untiy基本API 角度旋转自转相对于某一个轴 转多少度相对于某一个点转练习 角度 this.transform.rotation(四元数)界面上的xyz(相对于世界坐标) this.transform.eulerAngles;相对于父对象 this.transform.localEulerAngles;设置角度和设置位置一样,不能单独设置xz…...

Java基础常见面试题总结(上)
基础概念与常识 Java 语言有哪些特点? 简单易学(语法简单,上手容易);面向对象(封装,继承,多态);平台无关性( Java 虚拟机实现平台无关性)&…...

4 -《本地部署开源大模型》在Ubuntu 22.04系统下部署运行ChatGLM3-6B模型
在Ubuntu 22.04系统下部署运行ChatGLM3-6B模型 大模型部署整体来看并不复杂,且官方一般都会提供标准的模型部署流程,但很多人在部署过程中会遇到各种各样的问题,很难成功部署,主要是因为这个过程会涉及非常多依赖库的安装和更新及…...

本地如何使用Pycharm连接远程服务器调试torchrun
pycharm 远程连接服务器并且debug, 支持torch.distributed.launch debug_pycharm远程debug-CSDN博客 上面这个博客写的真的非常好,记录一下,需要注意该博主的主机为mac 本人可调试版本为: 可直接运行版本为:...
Visual Studio 2022常用快捷键
1. 基本编辑快捷键 Ctrl X:剪切选中内容Ctrl C:复制选中内容Ctrl V:粘贴内容Ctrl Z:撤销Ctrl Y:重做Ctrl Shift L:删除当前行Ctrl K, Ctrl C:注释选中的代码Ctrl K, Ctrl U…...

mysql innodb 引擎如何直接复制数据库文件?
mysql innodb 引擎如何直接复制数据库文件?介绍如下: 1、首先找到数据库文件所在位置 一般可以看my.conf/my.ini配置的文件的“datadir” 看示例: “MAMP”在Macos下的数据库文件位置: /Library/Application Support/appsolu…...
python中的global和nonlocal关键字以及闭包和模块
global i 这样的用法在于 Python 中,但需要在一个函数内部使用,以便将变量 i 声明为全局变量。让我们来详细讲解一下它的用法。 什么是全局变量? 全局变量是指在函数外部定义的变量,可以在任何函数中访问和修改。如果你需要在函数…...

LabVIEW风机滚动轴承监测系统
矿井主通风机作为矿井中最重要的通风设备,一旦出现故障,不仅会影响矿井内的空气质量,还可能引发安全事故。研究表明,通风机中约30%的故障是由轴承问题引起的。因此,能够实时监控矿井主通风机轴承状态的系统,…...
第1节 什么是鸿蒙系统
鸿蒙系统(HarmonyOS)是华为公司发布的一款基于微内核的面向全场景的分布式操作系统。以下是对它的具体介绍: 1. 核心特点: • 分布式能力:这是鸿蒙系统的核心优势之一。它能够将多种不同类型的智能终端设备连接起来&a…...
CentOS 7 将 YUM 源更改为国内镜像源
在 CentOS 7 中,将 YUM 源更改为国内的阿里云镜像源可以提高软件包的下载速度。以下是具体的步骤: 1. 备份原有 YUM 源配置 首先,建议你备份当前的 YUM 源配置,以防后续需要恢复: sudo cp -r /etc/yum.repos.d /etc…...

python调用dircmp进行文件夹比较
不同电脑上的同一部署文件,由于更新频率不相同导致两边内容有差异,需要比较两边的文件夹及文件差异。之前写过批量修改文件名的Python代码,因此优先想用python处理。 百度“python 文件夹对比”,不少文章都是自己实现的文件夹…...
微信小程序 - 供应链系统设计
文章目录 一、系统概述二、系统架构设计三、系统安全设计四、系统性能优化五、系统部署与维护 在当今数字化时代,供应链管理对于企业的高效运营至关重要。微信小程序作为一种便捷的移动应用形式,为供应链系统的开发提供了新的机遇。本文将从系统架构设计…...

嵌入式学习-IO进程-Day03
嵌入式学习-IO进程-Day03 IO进程 获取文件属性(stat) 库 库的概念 库的分类 静态库的制作 动态库的制作 进程 进程和程序的区别 进程的特点 进程三段 进程的类型 进程的运行状态 进程状态转换图(重点) 进程的函数接口 创建进程for…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...

ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
Vue 3 + WebSocket 实战:公司通知实时推送功能详解
📢 Vue 3 WebSocket 实战:公司通知实时推送功能详解 📌 收藏 点赞 关注,项目中要用到推送功能时就不怕找不到了! 实时通知是企业系统中常见的功能,比如:管理员发布通知后,所有用户…...
前端调试HTTP状态码
1xx(信息类状态码) 这类状态码表示临时响应,需要客户端继续处理请求。 100 Continue 服务器已收到请求的初始部分,客户端应继续发送剩余部分。 2xx(成功类状态码) 表示请求已成功被服务器接收、理解并处…...
React核心概念:State是什么?如何用useState管理组件自己的数据?
系列回顾: 在上一篇《React入门第一步》中,我们已经成功创建并运行了第一个React项目。我们学会了用Vite初始化项目,并修改了App.jsx组件,让页面显示出我们想要的文字。但是,那个页面是“死”的,它只是静态…...