当前位置: 首页 > news >正文

java中的数据类型

1 概述

Java 是一门面向对象的编程语言,其核心原则之一是一切皆对象。然而,基本数据类型(如 int、double、char 等)并非对象,不具备对象的特性,例如不能调用方法、不能参与继承体系等。而包装类(如 Integer、Double、Character 等)作为 Object 的子类,将基本数据类型进行了对象化封装,使得它们能够更好地融入到 Java 面向对象的编程环境中,符合面向对象的设计理念。如下图所示,内置类和对应的包装类:

内置类型(基本数据类型)对应的包装类(java.lang 包下)说明
byteByte8 位整数,用于表示范围相对较小的整数值,取值范围是 -128 到 127(包含边界值)。
shortShort16 位整数,可表示的数值范围比 byte 更大一些,范围是 -32768 到 32767(包含边界值)。
intInteger32 位整数,在日常编程中使用频率较高,能表示较广泛的整数值,范围是 -2147483648 到 2147483647(包含边界值)。
longLong64 位整数,适用于需要表示更大范围整数的场景,例如处理大文件的字节数、时间戳等,其取值范围极大。
floatFloat32 位浮点数,用于表示单精度的小数,在存储和运算时会存在一定的精度损失,常用于对精度要求不是特别高的浮点数值表示场景。
doubleDouble64 位浮点数,双精度浮点数,相比 float 能提供更高的精度,常用于科学计算、金融计算等对精度要求相对较高的领域,但同样存在精度问题。
charCharacter字符类型,用于表示单个字符,在 Java 中采用 Unicode 编码,可以表示世界上几乎所有的字符,例如字母、数字、标点符号以及各种语言的字符等。
booleanBoolean布尔类型,只有两个取值,即 true(真)和 false(假),常用于条件判断、逻辑控制等场景,比如在 if 语句、while 语句等控制结构中使用。

包装类中通用的方法:

方法分类方法定义(以Xxx代表具体包装类,T代表对应基本类型)说明适用所有包装类
拆箱(基本类型转换)T xxxValue()将包装类对象转换为对应的基本类型(如Integer.intValue()Character.charValue()
装箱(对象创建)static Xxx valueOf(T value)将基本类型转换为包装类对象(可能使用缓存,提高效率)
字符串解析为基本类型static T parseXxx(String s)将字符串解析为对应基本类型(如Integer.parseInt("123")Boolean.parseBoolean("true")Character
字符串解析(带进制)static T parseXxx(String s, int radix)按指定进制(2-36)解析字符串(仅整数型包装类支持,如Integer.parseInt("1010", 2)整数型(Integer/Long/Byte/Short
字符串转换static String toString(T value)将基本类型转换为字符串(如Integer.toString(123)Boolean.toString(true)
对象转字符串String toString()重写ObjecttoString(),返回包装类对象的字符串表示
数值比较static int compare(T a, T b)比较两个基本类型的值,返回-1(a<b)、0(a==b)、1(a>b)
常量:最大值static final T MAX_VALUE表示对应基本类型的最大值(如Integer.MAX_VALUEByte.MAX_VALUEBoolean
常量:最小值static final T MIN_VALUE表示对应基本类型的最小值(如Long.MIN_VALUEFloat.MIN_VALUEBoolean
常量:位数static final int SIZE表示对应基本类型的二进制位数(如Integer.SIZE=32Double.SIZE=64Boolean

对于Character 类型表示的Unicode 编码范围(0到65535),是字符编码的边界值。

2 不同数据类型的取值范围与使用场景

包装类对应基本类型占用内存(位)数值范围精度特性典型场景
Bytebyte8−27-2^727 ~ 27−12^7 - 1271(即 -128 ~ 127)整数,无精度损失存储小范围整数(如文件字节、ASCII 字符),节省内存。
Shortshort16−215-2^{15}215 ~ 215−12^{15} - 12151(即 -32768 ~ 32767)整数,无精度损失存储中等范围整数(如短数组、小范围计数),比 int 更省内存。
Integerint32−231-2^{31}231 ~ 231−12^{31} - 12311(即 -2147483648 ~ 2147483647)整数,无精度损失日常编程中最常用的整数类型(如循环计数、数组索引、普通数值计算)。
Longlong64−263-2^{63}263 ~ 263−12^{63} - 12631整数,无精度损失存储大范围整数(如时间戳、文件大小、大数值计数),避免溢出。
Floatfloat32±3.4×1038\pm 3.4 \times 10^{38}±3.4×1038(单精度,有效位数约 6-7 位)浮点数,可能有精度损失对精度要求不高的场景(如图形处理、科学计算中的近似值),内存占用比 double 小。
Doubledouble64±1.7×10308\pm 1.7 \times 10^{308}±1.7×10308(双精度,有效位数约 15-17 位)浮点数,精度高于 float,但仍可能有损失对精度要求较高的场景(如金融计算、科学实验数据),是默认浮点类型(如 1.2 默认为 double)。

3 浮点型存储方式

Java 中浮点型(floatdouble)遵循 IEEE 754 标准 进行存储,采用科学计数法的二进制形式表示,核心思想是用“符号位 + 指数位 + 尾数位”三部分存储数值,以平衡精度和表示范围。

float(32位单精度)的存储结构

32位总长度划分为三部分:

位区域位数作用
符号位(S)1位0表示正数,1表示负数(仅表示符号,不影响数值大小)。
指数位(E)8位存储指数的“偏移值”,用于表示数值的数量级(范围:-126 ~ +127)。
尾数位(M)23位存储二进制小数的有效数字(默认隐含一位整数“1”,实际精度为24位)。

示例:存储 0.5f

转换方式为乘二取整法,在IEE754中要求,第一位得为1,所以会将小数点右移并乘10的n次方达到上述目的,次数n位指数,小数部分为位数。

  • 二进制为 1.0 × 2⁻¹
  • 符号位 S=0(正数)
  • 指数 E = -1 + 127(偏移量)= 126 → 二进制 01111110
  • 尾数位 M = 0(因 1.0 的小数部分为0)
  • 最终32位存储:0 01111110 00000000000000000000000

double(64位双精度)的存储结构

64位总长度划分为三部分:

位区域位数作用
符号位(S)1位float,0为正,1为负。
指数位(E)11位存储指数的“偏移值”,表示范围更大(-1022 ~ +1023)。
尾数位(M)52位存储二进制小数的有效数字(默认隐含一位整数“1”,实际精度为53位)。

示例:存储 0.5(默认double

  • 二进制为 1.0 × 2⁻¹
  • 符号位 S=0
  • 指数 E = -1 + 1023(偏移量)= 1022 → 二进制 01111111110
  • 尾数位 M = 0
  • 最终64位存储:0 01111111110 00000000000000000000000000000000000000000000000000000000

floatdouble 的核心区别

类型总位数符号位指数位尾数位指数范围(二进制)指数范围(十进制)有效精度(二进制)有效精度(十进制)适用场景
float32位1位8位23位-126 ~ +127±3.4×10³⁸24位(含隐含位)6-7位精度要求低、内存敏感场景
double64位1位11位52位-1022 ~ +1023±1.7×10³⁰⁸53位(含隐含位)15-17位高精度计算(如金融、科学计算)

4 精确度问题

有些小数不能精确的转成小数,例如0.1:
以下是将十进制小数 0.1 转换为二进制小数的详细计算步骤,按照乘2取整的方法逐步推导( 乘 2 取整法):

实例

步骤一:初始化

我们要将十进制小数 0.1 转换为二进制,先记录下当前待转换的十进制小数为 0.1

步骤二:第一次乘2取整

将当前的十进制小数乘以 2,即:

此时,取乘积结果的整数部分作为二进制小数小数点后的第一位数字,这里整数部分是 0,所以二进制小数目前为 0.0

然后记录下此次乘积结果的小数部分 0.2,用于后续继续计算。

步骤三:第二次乘2取整

用上一步得到的小数部分 0.2 乘以 2,可得:

取这个乘积结果的整数部分作为二进制小数小数点后的第二位数字,整数部分为 0,此时二进制小数变为 0.00
同样,记录下此次乘积结果的小数部分 0.4 用于下一步计算。

步骤四:第三次乘2取整

用新得到的小数部分 0.4 乘以 2

取整数部分作为二进制小数小数点后的第三位数字,这里整数部分是 0,二进制小数更新为 0.000
接着记录下小数部分 0.8 继续下一步操作。

步骤五:第四次乘2取整

用小数部分 0.8 乘以 2

取整数部分 1 作为二进制小数小数点后的第四位数字,此时二进制小数变为 0.0001
记录下此次乘积结果的小数部分 0.6,用于后续计算。

步骤六:第五次乘2取整

0.6 乘以 2

取整数部分 1 作为二进制小数小数点后的第五位数字,二进制小数更新为 0.00011
再记录下小数部分 0.2,继续下一步运算。

步骤七:第六次乘2取整

用新出现的小数部分 0.2 乘以 2

取整数部分 0 作为二进制小数小数点后的第六位数字,二进制小数变为 0.000110
记录下小数部分 0.4,准备下一轮计算。

步骤八:后续循环

可以发现,从这一步开始,后续出现的小数部分 0.4 又回到了之前步骤三出现过的情况,后续的计算将会不断重复出现 0.40.81.61.2 等这些小数部分以及对应的取整结果,陷入循环。

所以,十进制小数 0.1 转换为二进制小数的结果是 0.00011001100110011...,这是一个无限循环的二进制小数,通常可以表示为 0.0\dot{0}110(在二进制下循环节为 0110)。

如果按照IEEE 754标准将其存储为 floatdouble 类型时,由于尾数位长度有限(float 的尾数位23位,double 的尾数位52位),只能截取前面有限的位数来近似表示这个无限循环的二进制小数,从而导致了精度损失。例如在 float 类型中存储时,实际存储的是这个无限循环二进制小数的近似值,并非精确的 0.1 在二进制下的完整表示。

Double的尾数有52位,而Float仅仅有23位,因此double具有更高的精度。

5 BigInteger和BigDecimal

在 Java 中,BigInteger和BigDecimal是两个用于高精度数值计算的类(你可能想说的是BigDecimal,Java 中并没有BigDouble这个类哦),它们解决了基本数据类型(如int、double等)在处理大数值以及高精度要求场景下的精度不足等问题。

BigInteger

BigInteger 是 Java 中用于表示任意精度整数的类,其存储方式与基本整数类型(如 int、long)有本质区别,核心是通过动态数组存储二进制原码的各位,从而支持任意大小的整数。BigInteger 内部通过一个 int[] 数组(名为 mag,即 “magnitude” 的缩写)存储整数的绝对值的二进制补码表示,并使用一个 int 类型的 signum 标记符号:signum:符号位,取值为 1(正数)、0(零)、-1(负数)。

实例

12345678901234567890(约10¹⁹)为例,来直观理解 BigIntegermag 数组的存储方式:

步骤1:计算整数的绝对值和二进制表示

  • 整数为正数,signum = 1(符号为正)。
  • 绝对值就是 12345678901234567890
  • 转换为二进制(简化表示,实际很长):
    10101101011110011100110111100111011011101011101011010110100010010

步骤2:按32位拆分二进制位(大端序)

mag 数组的每个元素是32位 int,按高位在前、低位在后的大端序存储,且不保留前导零:

  1. 将二进制从左到右(高位到低位)每32位分一组:

    • 第一组(最高位32位):1010110101111001110011011110011
    • 第二组(次高位32位):1011011101011101011010110100010
    • 第三组(剩余低位,不足32位补0,但因无需求前导零,实际存储有效位):0010(此处仅为示例,实际会补齐32位但去除前导零)。
  2. 每组转换为十进制 int 值,存入 mag 数组:

    • 第一组对应 int 值:2874452659
    • 第二组对应 int 值:2995155810
    • 第三组对应 int 值:2(简化后)。
  3. 最终 mag 数组为:[2874452659, 2995155810, 2]

BigDecimal

BigDecimal 主要是为了解决浮点数(如 float、double)在运算时因二进制存储格式而产生精度损失的问题。在很多对精度要求严苛的领域,比如金融行业(涉及货币金额计算、利息计算、汇率换算等)、科学计算中需要精确数值的情况等,都需要使用 BigDecimal 来确保计算结果的准确性。

BigDecimal 采用 “整数数组 + 小数点位置 + 符号位” 的三元存储结构,彻底解决了浮点型(float/double)的精度损失问题,以下是其存储方式的详细解析:

核心存储结构

BigDecimal 内部通过三个关键部分表示一个十进制数:

  1. BigInteger intVal:存储数值的"无小数点整数形式"(所有有效数字,不含小数点)。
  2. int scale:表示小数点位置(即小数部分的位数,scale ≥ 0 时为小数位数,scale < 0 时表示整数部分后有 -scale 个零)。
  3. 符号位:由 intVal 内部的 signum 变量表示(1 为正,-1 为负,0 为零)。

存储细节拆解

123.45-67.890 为例,具体说明存储逻辑:

例1:存储 123.45(正数)
  • 步骤1:处理数值为无小数点整数
    去掉小数点,保留所有有效数字 → 12345
    这部分由 intValBigInteger 类型)存储,其内部 mag 数组为 [12345](二进制拆分的整数绝对值)。

  • 步骤2:记录小数点位置(scale
    原数小数点后有 2 位 → scale = 2

  • 步骤3:标记符号
    正数 → signum = 1

    最终存储:intVal=12345 + scale=2 + signum=1 → 还原为 12345 / 10² = 123.45

例2:存储 -67.890(负数)
  • 步骤1:处理数值为无小数点整数
    去掉小数点和负号 → 67890(注意:末尾的 0 是有效数字,会保留)。
    intValmag 数组为 [67890]

  • 步骤2:记录小数点位置(scale
    原数小数点后有 3 位 → scale = 3

  • 步骤3:标记符号
    负数 → signum = -1

    最终存储:intVal=67890 + scale=3 + signum=-1 → 还原为 -67890 / 10³ = -67.890

特殊场景处理

  1. 整数(如 123)
    scale = 0(无小数部分),存储为 intVal=123 + scale=0123 / 10⁰ = 123

  2. 纯小数(如 0.0045)
    无小数点整数为 45scale = 445 / 10⁴ = 0.0045

  3. 科学计数法(如 1.23e+5 = 123000)
    等价于 123000scale = -2scale < 0 表示整数部分后补 2 个零) → 123 × 10² = 123000

总结

BigDecimal 通过 “剥离小数点保留全部有效数字(intVal)+ 记录小数点位置(scale)+ 单独标记符号” 的设计,实现了十进制数的完全精确存储。这种方式避开了二进制与十进制转换的天然矛盾,是高精度场景(如货币计算)的必备工具。

其核心思想可概括为:“用整数存储所有有效数字,用 scale 记住小数点在哪,用 signum 标记正负”

有效数字的存储和BigInteger 一致也就是,BigDecimal可以表示任意精度的数字。

http://www.dtcms.com/a/353337.html

相关文章:

  • 《FastAPI零基础入门与进阶实战》第14篇:ORM之第一个案例改善-用户查询
  • 【图文介绍】PCIe 6.0 Retimer板来了!
  • 快速上手对接币安加密货币API
  • 《Linux 网络编程四:TCP 并发服务器:构建模式、原理及关键技术(以select )》
  • 3 无重复字符的最长子串
  • Windows系统之不使用第三方软件查看电脑详细配置信息
  • 基于linux系统的LIRC库学习笔记
  • Ubuntu 的磁盘管理
  • [java] 控制三个线程按顺序交替输出数字1、2、3
  • 【新版发布】Apache DolphinScheduler 3.3.1 正式上线:更稳、更快、更安全!
  • TensorFlow 面试题及详细答案 120道(21-30)-- 模型构建与神经网络
  • 数据结构:创建堆(或者叫“堆化”,Heapify)
  • 增强CD47检查点免疫治疗:高通量发现增强巨噬细胞吞噬作用的小分子协同剂
  • nestjs 连接redis
  • HIVE的Window functions窗口函数【一】
  • 手写题(面试)
  • LeetCode算法日记 - Day 24: 颜色分类、排序数组
  • LeetCode - 155. 最小栈
  • Python Imaging Library (PIL) 全面指南:PIL基础入门-跨平台安装与环境配置
  • Redis 数据结构
  • Linex系统网络管理(二)
  • 【yocto】Yocto Project 核心:深入了解.inc文件
  • Java中使用Spring Boot+Ollama构建本地对话机器人
  • Maven 依赖传递与排除基础逻辑
  • Astah UML 中,状态机(State Machine)的建模最合适使用「UML 状态图(State Diagram)」
  • 轻量级自动驾驶多视图视觉问答模型-EM-VLM4AD
  • 鸿蒙HarmonyOS状态管理装饰器详解
  • perccli 工具
  • 鸿蒙网络编程系列62-仓颉版使用Request部件上传多个文件到服务端
  • 华中科大联手小米推出ReCogDrive:自动驾驶迎来“认知革命”!