Langchain系列文章目录
01-玩转LangChain:从模型调用到Prompt模板与输出解析的完整指南
02-玩转 LangChain Memory 模块:四种记忆类型详解及应用场景全覆盖
03-全面掌握 LangChain:从核心链条构建到动态任务分配的实战指南
04-玩转 LangChain:从文档加载到高效问答系统构建的全程实战
05-玩转 LangChain:深度评估问答系统的三种高效方法(示例生成、手动评估与LLM辅助评估)
06-从 0 到 1 掌握 LangChain Agents:自定义工具 + LLM 打造智能工作流!
07-【深度解析】从GPT-1到GPT-4:ChatGPT背后的核心原理全揭秘
PyTorch系列文章目录
机器学习系列文章目录
Java系列文章目录
01-【Java-Day 1】开启编程之旅:详解Java JDK安装、环境配置与运行HelloWorld
02-【Java-Day 2】Java开发利器:IntelliJ IDEA入门教程(安装、配置、项目创建、调试)
03-【Java-Day 3】代码的基石:深入理解Java变量与基本数据类型(整型、浮点型篇)
文章目录
前言
大家好!欢迎来到 Java 学习之旅的第三天。在前两篇文章中,我们已经了解了 Java 的基本概念,搭建了开发环境,并熟悉了 IDE 的使用。今天,我们将深入探讨编程中最基础也最重要的概念之一 —— 变量 (Variable) 以及 Java 中的 基本数据类型 (Primitive Data Types)。理解它们是编写任何有意义程序的前提。就像盖房子需要砖块一样,变量和数据类型就是我们构建代码逻辑的基石。本篇将重点介绍变量的概念以及 Java 八种基本数据类型中的整型和浮点型。
一、什么是变量?
想象一下,在程序运行过程中,我们需要临时存储数据,比如用户的输入、计算的中间结果、或者某个对象的状态。变量就扮演了这个“临时存储”的角色。
1.1 变量的概念
从本质上讲,变量是内存中的一块存储区域。我们可以给这块区域起一个名字(变量名),并通过这个名字来访问或修改存储在其中的数据。你可以把它想象成一个带标签的盒子,盒子里可以放东西(数据),标签就是变量名,方便我们找到这个盒子。
变量存储的数据是可变的,这也是它名字的由来。程序可以通过变量名来读取数据,也可以向变量中存入新的数据。
1.2 变量的声明
在 Java 中使用变量之前,必须先声明它。声明变量的目的是告诉编译器:“我需要一块内存空间,用来存储某种类型的数据,请给这块空间起个名字叫 XXX”。
声明变量的基本语法如下:
dataType variableName;
dataType
: 指定了变量可以存储的数据类型。例如,int
表示整数,double
表示双精度浮点数。数据类型决定了变量在内存中占用的空间大小以及可以进行的操作。我们稍后会详细介绍 Java 的数据类型。variableName
: 你给变量起的名字,也就是变量的标识符。需要遵循一定的命名规则。
示例:
// 声明一个整型变量,名为 age
int age;
// 声明一个双精度浮点型变量,名为 price
double price;
// 也可以在一行声明多个同类型的变量,用逗号隔开(但不推荐,可读性稍差)
int count, score;
1.3 变量的初始化
声明变量后,它在内存中就有了一个位置,但里面通常是空的或者是一个不确定的默认值(取决于变量类型和上下文,局部变量没有默认值,必须初始化)。为了让变量有明确的意义,我们需要给它赋一个初始值,这个过程称为初始化。
初始化可以通过赋值运算符 =
来完成。
语法:
-
先声明,后初始化:
dataType variableName; // 声明 variableName = value; // 初始化 (赋值)
-
声明的同时进行初始化: (推荐方式)
dataType variableName = value; // 声明并初始化
value
: 要赋给变量的具体值,这个值的类型必须与声明变量时指定的dataType
兼容。
示例:
// 1. 先声明,后初始化
int year; // 声明一个整型变量 year
year = 2025; // 给 year 赋值
double salary; // 声明一个双精度浮点型变量 salary
salary = 8888.88; // 给 salary 赋值
// 2. 声明的同时进行初始化 (更常用)
int month = 4; // 声明整型变量 month 并初始化为 4
double weight = 65.5; // 声明双精度浮点型变量 weight 并初始化为 65.5
注意: 在方法内部声明的变量(局部变量)在使用前必须进行初始化,否则编译器会报错。
1.4 变量的命名规范
给变量起一个好名字非常重要,它能大大提高代码的可读性和可维护性。Java 变量命名需要遵循以下规范:
(1) 基本规则 (强制)
- 变量名可以包含字母、数字、下划线 (
_
) 和美元符号 ($
)。 - 变量名不能以数字开头。
- 变量名区分大小写 (
age
和Age
是两个不同的变量)。 - 变量名不能是 Java 的关键字或保留字 (例如
int
,double
,class
,public
等)。 - 变量名长度理论上没有限制,但应见名知意,尽量简洁明了。
(2) 驼峰命名法 (推荐)
- 小驼峰命名法 (Lower Camel Case):这是 Java 社区广泛推荐的变量命名风格。
- 如果变量名只有一个单词,则所有字母小写,例如
age
,name
,score
。 - 如果变量名由多个单词组成,则第一个单词首字母小写,后续每个单词的首字母大写,例如
userName
,studentAge
,maxSpeed
,orderDetailList
。
- 如果变量名只有一个单词,则所有字母小写,例如
示例 (好的命名 vs 不好的命名):
// --- 好的命名 (遵循小驼峰,见名知意) ---
int studentCount; // 学生数量
String firstName; // 名字
double averageScore; // 平均分
boolean isAvailable; // 是否可用
// --- 不好的命名 ---
// int studentcount; // (不推荐) 全小写,单词间不易区分
// String first_name; // (不推荐) C/Python 风格,Java 中少用
// double avgScr; // (不推荐) 过于缩写,可能造成歧义
// boolean flag; // (不推荐) 过于笼统,无法体现变量用途
// int $price; // (不推荐) 虽然合法,但 $ 通常有特殊含义或用于自动生成代码
// int class; // (错误) 使用了关键字
// int 1stPlace; // (错误) 数字开头
养成良好的命名习惯是专业程序员的基本素养。
二、Java的基本数据类型 - 整型
在 Java 中,数据类型分为两大类:基本数据类型 (Primitive Data Types) 和 引用数据类型 (Reference Data Types)。基本数据类型是 Java 语言内置的、最基础的数据类型,它们直接存储数据值。Java 共有 8 种基本数据类型,我们将分两篇来介绍。
本篇先介绍用于表示整数的四种类型:byte
, short
, int
, long
。它们的主要区别在于占用的内存空间大小和能够表示的数值范围。
2.1 整型概述
整型用于表示没有小数部分的数值。根据数值范围和内存占用的不同,Java 提供了四种整型:
类型 (Type ) | 占用空间 (Bytes) | 占用位数 (Bits) | 范围 (Range ) | 默认值 (Default Value ) |
---|---|---|---|---|
byte | 1 | 8 | − 128 -128 −128 到 127 127 127 | 0 |
short | 2 | 16 | − 32 , 768 -32,768 −32,768 到 32 , 767 32,767 32,767 | 0 |
int | 4 | 32 | − 2 31 -2^{31} −231 到 2 31 − 1 2^{31}-1 231−1 (约 ± \pm ± 21亿) | 0 |
long | 8 | 64 | − 2 63 -2^{63} −263 到 2 63 − 1 2^{63}-1 263−1 (非常大) | 0L |
2.2 byte
类型
(1) 概念与用途
byte
是 Java 中占用内存最小的整型。它使用 1 个字节(8 位)来存储数据。
主要用途:
- 在需要节省内存的场景,特别是处理大量数据时(如图像处理、文件流、网络数据传输中的原始字节数据)。
- 当数据的范围确定在 -128 到 127 之间时。
(2) 占用空间与范围
- 占用空间:1 字节 (8 bits)
- 范围: − 128 -128 −128 到 127 127 127 ($ -2^7 $ 到 $ 2^7 - 1 $)
(3) 字面量与示例
直接写出的整数值被称为字面量 (Literal)。整数字面量默认是 int
类型。如果一个整数字面量在 byte
的表示范围内,可以直接赋值给 byte
类型的变量。
byte b1 = 100; // 100 在 -128 到 127 之间,可以直接赋值
byte b2 = -50; // -50 也在范围内
// byte b3 = 130; // 编译错误!130 超出了 byte 的范围 (-128 ~ 127)
2.3 short
类型
(1) 概念与用途
short
类型占用 2 个字节(16 位),表示范围比 byte
大,比 int
小。在实际开发中,它的使用频率相对较低,除非有特定的接口要求或内存限制非常严格。
(2) 占用空间与范围
- 占用空间:2 字节 (16 bits)
- 范围: − 32 , 768 -32,768 −32,768 到 32 , 767 32,767 32,767 ($ -2^{15} $ 到 $ 2^{15} - 1 $)
(3) 字面量与示例
同样,如果整数字面量在 short
的表示范围内,可以直接赋值。
short s1 = 10000; // 10000 在 -32768 到 32767 之间
short s2 = -2000;
// short s3 = 40000; // 编译错误!40000 超出了 short 的范围
2.4 int
类型
(1) 概念与用途
int
是 Java 中最常用的整型类型。它占用 4 个字节(32 位)。当你直接在代码中写一个整数字面量时(如 10
, 99
, -500
),编译器会默认将其视为 int
类型。
主要用途:
- 绝大多数整数运算和计数场景。
- 数组索引。
- 循环计数器等。
(2) 占用空间与范围
- 占用空间:4 字节 (32 bits)
- 范围: − 2 , 147 , 483 , 648 -2,147,483,648 −2,147,483,648 到 2 , 147 , 483 , 647 2,147,483,647 2,147,483,647 (约正负 21 亿,$ -2^{31} $ 到 $ 2^{31} - 1 $)。这个范围对于大多数日常计算来说足够了。
(3) 字面量与示例
int count = 1000000; // 百万级,int 轻松容纳
int temperature = -10;
// 可以使用下划线分隔数字,提高可读性 (Java 7+),下划线不影响数值本身
int largeNumber = 2_147_483_647; // int 的最大值
int population = 1_400_000_000; // 14亿
2.5 long
类型
(1) 概念与用途
当 int
类型的范围不足以表示所需的整数时(例如,需要存储非常大的数字,如全球人口、大型文件的大小、精确到毫秒的时间戳等),就需要使用 long
类型。它占用 8 个字节(64 位)。
(2) 占用空间与范围
- 占用空间:8 字节 (64 bits)
- 范围: − 9 , 223 , 372 , 036 , 854 , 775 , 808 -9,223,372,036,854,775,808 −9,223,372,036,854,775,808 到 9 , 223 , 372 , 036 , 854 , 775 , 807 9,223,372,036,854,775,807 9,223,372,036,854,775,807 ($ -2^{63} $ 到 $ 2^{63} - 1 $),这是一个极其巨大的范围。
(3) 字面量与示例
要表示一个 long
类型的字面量,需要在数字后面加上后缀 L
或 l
(强烈推荐使用大写 L
,因为小写 l
容易和数字 1
混淆)。
// 必须加 L 或 l 后缀,否则超过 int 范围的数字会编译错误
long worldPopulation = 7_800_000_000L; // 正确,使用 L 后缀
long fileSize = 1024L * 1024 * 1024 * 5; // 计算结果可能超过 int 范围,使用 L
long distanceToSun = 149_600_000_000L; // 太阳距离,单位米
// 即使数值在 int 范围内,也可以加上 L 显式表示为 long 类型
long smallLong = 100L;
重点: 如果一个整数值超过了 int
的最大范围(约21亿),即使你要把它赋值给 long
类型的变量,也必须在字面量后面加上 L
后缀,否则编译器会先尝试将其当作 int
处理而导致编译错误(“integer number too large”)。
2.6 整型选择建议
- 首选
int
: 在绝大多数情况下,int
是最常用的整数类型,其范围足够满足大部分计算需求,运算效率也较好。 - 使用
long
: 当数值可能超过int
的范围时(例如,处理时间戳、数据库主键ID、大文件大小等)。 - 谨慎使用
byte
和short
: 仅在内存资源极其宝贵或需要处理特定格式的二进制数据(如文件流、网络协议)时考虑使用。在进行算术运算时,byte
和short
类型的值会被自动提升为int
类型进行计算,可能需要强制类型转换,反而增加代码复杂度。
潜在问题: 整型运算可能发生溢出 (Overflow)。当运算结果超出了该类型所能表示的最大范围时,结果会像里程表一样“翻转”,变成一个意想不到的负数(或正数)。例如:
int maxInt = Integer.MAX_VALUE; // 获取 int 的最大值 (2147483647)
int overflowResult = maxInt + 1;
System.out.println(overflowResult); // 输出会是 -2147483648 (int 的最小值)
// 解决方案:如果预知结果可能很大,应使用范围更大的类型,如 long
long largeSum = (long)maxInt + 1; // 先将 maxInt 转换为 long 再加 1
System.out.println(largeSum); // 输出 2147483648
三、Java的基本数据类型 - 浮点型
浮点型用于表示带有小数部分的数值,也就是我们通常说的实数。Java 提供了两种浮点类型:float
和 double
。它们基于 IEEE 754 标准实现。
3.1 浮点型概述
浮点数在计算机中的表示方式比较复杂,它由符号位、指数位和尾数位组成。这导致浮点数通常是近似值,可能存在精度损失。
类型 (Type ) | 占用空间 (Bytes) | 占用位数 (Bits) | 大致精度 (Decimal Digits) | 范围 (Range ) | 默认值 (Default Value ) |
---|---|---|---|---|---|
float | 4 | 32 | 约 6-7 位 | 较大,但精度有限 | 0.0f |
double | 8 | 64 | 约 15 位 | 非常大,精度更高 | 0.0d |
3.2 float
类型
(1) 概念与用途
float
类型称为单精度浮点型,占用 4 个字节(32 位)。它提供的精度相对较低。
用途:
- 在内存要求比较严格,且对精度要求不高的场景(如图形库中的某些计算)。
- 需要存储大量浮点数时,为了节省空间。
(2) 占用空间与精度
- 占用空间:4 字节 (32 bits)
- 精度:大约能精确表示 6-7 位十进制有效数字。
(3) 字面量与示例
浮点数字面量默认是 double
类型。要表示一个 float
类型的字面量,必须在数字后面加上后缀 F
或 f
。
// 必须加 F 或 f 后缀
float price = 19.99F;
float pi = 3.14f;
float negativeValue = -0.5f;
// float height = 1.75; // 编译错误!1.75 默认是 double 类型,不能直接赋给 float
3.3 double
类型
(1) 概念与用途
double
类型称为双精度浮点型,占用 8 个字节(64 位)。它是 Java 中默认且最常用的浮点类型,因为它提供了更高的精度。
用途:
- 绝大多数需要表示小数的场景。
- 科学计算、工程计算等需要较高精度的领域。
Math
类库中的函数(如sin
,cos
,sqrt
)通常接收和返回double
类型。
(2) 占用空间与精度
- 占用空间:8 字节 (64 bits)
- 精度:大约能精确表示 15 位十进制有效数字。
(3) 字面量与示例
浮点数字面量默认就是 double
类型,所以后缀 D
或 d
是可选的(通常省略)。
double accountBalance = 12345.67; // 默认就是 double
double gravity = 9.8;
double temperature = -15.5d; // 加上 d 后缀也可以
3.4 浮点型注意事项
(1) 精度问题
这是使用浮点数时最需要注意的一点。由于计算机使用二进制表示小数,很多十进制小数无法被精确地表示为二进制浮点数,只能存储一个非常接近的近似值。这会导致一些看似奇怪的计算结果。
double d1 = 0.1;
double d2 = 0.2;
System.out.println(d1 + d2); // 输出可能不是 0.3,而是类似 0.30000000000000004
double result = 1.0 - 0.9;
System.out.println(result); // 输出可能不是 0.1,而是类似 0.09999999999999998
// 因此,绝对不能使用 == 直接比较两个浮点数是否相等!
double x = 0.1 + 0.2;
double y = 0.3;
System.out.println(x == y); // 输出 false!
如何比较浮点数?
通常采用差值比较法:判断两个浮点数的差的绝对值是否小于一个非常小的数(称为精度容忍度或epsilon)。
double epsilon = 1e-6; // 例如,设置一个百万分之一的精度容忍度
if (Math.abs(x - y) < epsilon) {
System.out.println("x 和 y 在允许的误差范围内相等");
} else {
System.out.println("x 和 y 不相等");
}
需要精确计算的场景怎么办?
如果你的应用场景对精度有严格要求(例如金融计算、货币运算),绝对不要使用 float
或 double
。应该使用 java.math.BigDecimal
类,它可以进行任意精度的十进制运算。(我们将在后续文章中介绍 BigDecimal
)
(2) 特殊值
浮点类型还包含一些特殊的值:
Float.POSITIVE_INFINITY
/Double.POSITIVE_INFINITY
: 正无穷大 (例如1.0 / 0.0
)Float.NEGATIVE_INFINITY
/Double.NEGATIVE_INFINITY
: 负无穷大 (例如-1.0 / 0.0
)Float.NaN
/Double.NaN
: Not a Number (非数值,表示一个无效或未定义的结果,例如0.0 / 0.0
,Math.sqrt(-1)
)
注意: NaN
与任何值(包括它自己)进行 ==
比较都返回 false
。要判断一个值是否是 NaN
,应该使用 Float.isNaN()
或 Double.isNaN()
方法。
double result = 0.0 / 0.0;
System.out.println(result == Double.NaN); // 输出 false!
System.out.println(Double.isNaN(result)); // 输出 true
四、总结
今天我们学习了 Java 编程的两个核心基础概念:变量和基本数据类型中的整型与浮点型。
- 变量 (Variable):是内存中用于存储数据的命名区域,其值可以改变。使用前必须声明(指定类型和名称),并且通常需要初始化(赋予初始值)。变量命名推荐使用小驼峰命名法 (lowerCamelCase),做到见名知意。
- 整型 (Integer Types):用于表示整数。
byte
: 1字节,范围 -128 到 127。用于节省内存或处理原始字节数据。short
: 2字节,范围约 $\pm$3万。使用较少。int
: 4字节,范围约 $\pm$21亿。最常用的整数类型,整数字面量默认为int
。long
: 8字节,范围非常大。用于存储超过int
范围的整数,字面量需要加后缀L
。
- 浮点型 (Floating-Point Types):用于表示带小数的数值。
float
: 4字节,单精度,约 6-7 位有效数字。字面量需要加后缀F
或f
。double
: 8字节,双精度,约 15 位有效数字。最常用的浮点类型,浮点数字面量默认为double
(后缀D
或d
可选)。
- 浮点数精度问题:
float
和double
存储的是近似值,不适用于需要精确计算的场景(如金融),且不能直接用==
比较相等性。 - 字面量 (Literal):直接写在代码中的数值(如
100
,3.14
,100L
,19.9F
)。整数字面量默认为int
,浮点数字面量默认为double
。
掌握变量和基本数据类型是 Java 编程的起点。在下一篇文章 《代码的基石 - 变量与数据类型 (下)》 中,我们将继续学习剩下的两种基本数据类型:字符型 (char
) 和 布尔型 (boolean
),以及非常重要的 数据类型转换 知识。敬请期待!
希望这篇文章对你理解 Java 变量和基本数据类型有所帮助。如果你有任何疑问或建议,欢迎在评论区留言讨论!