外观
第 2 章 变量、常量与数据类型:给数据一个家
阅读目标
- 理解变量的概念、作用以及命名规则。
- 掌握 Java 的 8 种基本数据类型及
String。- 学会声明、赋值变量以及使用常量。
- 掌握数组的基本用法和字符串的常用方法。
- 理解基本类型与引用类型的区别及类型转换规则。
在上一章,我们已经成功地让程序打印出了文字,甚至做了一些简单的数学计算。在练习中,我们用到了 int a = 10; 这样的代码。这里的 a 就是一个变量。
2.1 什么是变量?
你可以把变量想象成一个贴着标签的透明储物盒。
- 盒子:是计算机内存中一块用来存放数据的空间。
- 标签:就是我们给这块空间取的名字,即变量名。
- 盒里的东西:就是存放在这块空间里的值。
最重要的是,盒里的东西(值)是可以随时更换的,这也就是它为什么被称为“变”量。
2.1.1 变量的声明与赋值
在 Java 中,声明和使用变量遵循一个固定的格式。
- 声明语法:
type varName; - 赋值语法:
varName = value; - 声明并赋值:
type varName = value;
java
/**
* 这是一个演示如何声明和使用变量的简单程序。
* 我们会创建一个变量来存储机器人的速度,并改变它。
*/
public class RobotSpeed {
public static void main(String[] args) {
// 1. 声明一个整数类型的变量,名叫 "speed"
// (type: int, varName: speed)
int speed;
// 2. 给变量 speed 赋值,把数字 10 放进盒子里
// (varName: speed, value: 10)
speed = 10;
// 3. 打印出变量 speed 的值
System.out.println("机器人现在的速度是: " + speed);
// 4. 我们可以改变变量的值
speed = 20; // 现在把 20 放到盒子里,原来的 10 就被替换掉了
System.out.println("机器人加速了!现在的速度是: " + speed);
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
变量的命名规则
给变量取个好名字很重要,就像给你的机器人取名一样。请遵循以下规则:
- 开头:必须以字母、下划线(
_)或美元符号($)开头。 - 组成:后面可以跟字母、数字、下划线或美元符号。
- 大小写:
speed和Speed是两个完全不同的变量。 - 关键字:不能使用 Java 的保留字,比如
public,class,int等。 - 驼峰命名法 (CamelCase):建议使用有意义的英文单词,当有多个单词时,从第二个单词开始首字母大写,例如
motorSpeed,robotPosition。这能极大提高代码的可读性。
2.2 数据类型:不同规格的储物盒
程序需要处理各种各样的数据,比如整数、小数、单个文字、对或错等。为了能最高效地利用内存空间,Java 规定了不同种类的“储物盒”,也就是数据类型。
Java 是强类型语言
"强类型"意味着:
- 必须先声明,后使用:在使用一个变量前,必须先告诉 Java 你需要一个什么类型、叫什么名字的“盒子”。
- 类型必须匹配:声明了是“整数盒子”(
int),就不能往里面放文字("你好")。
2.2.1 基本数据类型
Java 的数据类型分为两大类:基本数据类型和引用数据类型。
这是 Java 内置的 8 种基础类型,它们直接存储数据值。
| 类别 | 数据类型 | 关键字 | 占用空间 | 描述与用途 |
|---|---|---|---|---|
| 整数 | 字节型 | byte | 1 字节 | 存储很小的整数 (-128 到 127) |
| 短整型 | short | 2 字节 | 存储较小的整数 | |
| 整型 | int | 4 字节 | 最常用的整数类型,足够大多数场景使用 | |
| 长整型 | long | 8 字节 | 存储非常巨大的整数 (值后面要加 L,如 3000000000L) | |
| 浮点数 | 单精度 | float | 4 字节 | 存储小数,精度较低 (值后面要加 f,如 3.14f) |
| 双精度 | double | 8 字节 | 最常用的小数类型,精度更高 | |
| 字符 | 字符型 | char | 2 字节 | 存储单个字符,用单引号'括起来,如 'A', '中' |
| 逻辑 | 布尔型 | boolean | 1 字节 | 只有两个值:true (真) 和 false (假),用于逻辑判断 |
小心浮点数的精度陷阱
计算机在存储小数时,可能会有微小的误差,因为二进制无法精确表示所有十进制小数。这会导致一些奇怪的结果。 布尔型只有一个 boolean 类型,用于表示逻辑上的“真”或“假”。在 Java 语言中,boolean 类型的数值只能是 true 或 false,不能用 0 或非 0 来代表。其他基本数据类型的值也不能被转换成 boolean 类型。
java
System.out.println(0.1 + 0.2); // 输出 0.30000000000000004
System.out.println(0.1 + 0.2 == 0.3); // 输出 false1
2
2
因此,永远不要用 == 直接比较两个浮点数是否相等!
2.2.2 引用数据类型
引用类型不直接存储数据本身,而是存储数据所在位置的“地址”或“引用”。我们先学习两种最重要的引用类型:String 和数组。
字符串 (String)
String 用来存储一串文字,比如 "Hello, FTC!"。它的值必须用双引号 " 括起来。
数组基础
数组就像一个“储物柜”,它里面有一排连续的、大小相同的储物格,可以存放同一类型的多个数据。
- 声明数组:
type[] arrayName; - 创建数组:
arrayName = new type[length];(length 指明柜子有多少格) - 声明并创建:
type[] arrayName = new type[length];
数组的索引从 0 开始
数组的第一个元素的索引是 0,第二个是 1,以此类推。一个长度为 5 的数组,其索引范围是 0 到 4。
java
/**
* 本程序演示数组的基本用法:创建、赋值和访问。
*/
public class ArrayExample {
public static void main(String[] args) {
// 声明并创建一个能存放 4 个整数的数组,名为 motorPowers
int[] motorPowers = new int[4];
// 使用索引为每个马达设置动力值
motorPowers[0] = 100; // 第 1 个马达
motorPowers[1] = 95; // 第 2 个马达
motorPowers[2] = -100;// 第 3 个马达
motorPowers[3] = -95; // 第 4 个马达
// 访问并打印第 2 个马达的动力值
System.out.println("第二个马达的动力是: " + motorPowers[1]); // 输出 95
// 修改第 1 个马达的动力值
motorPowers[0] = 50;
System.out.println("第一个马达的动力更新为: " + motorPowers[0]); // 输出 50
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2.3 常用方法:操作数据
2.3.1 字符串(String)的常用方法
String 类型自带了很多便捷的方法来处理文本。
| 方法 | 说明 | 示例 |
|---|---|---|
length() | 返回字符串的长度(字符个数) | "Hello".length() 返回 5 |
equals(anotherString) | 比较两个字符串的内容是否完全相同 | "A".equals("a") 返回 false |
equalsIgnoreCase(anotherString) | 比较字符串内容,忽略大小写 | "A".equalsIgnoreCase("a") 返回 true |
charAt(index) | 获取指定索引位置的单个字符 | "Java".charAt(1) 返回 'a' |
substring(beginIndex, endIndex) | 提取子字符串(从 beginIndex 到 endIndex-1) | "Robot".substring(1, 4) 返回 "obo" |
toUpperCase() / toLowerCase() | 转换为全大写或全小写 | "Ftc".toUpperCase() 返回 "FTC" |
2.3.2 数组的使用
| 用法 | 说明 | 示例 |
|---|---|---|
array.length | 属性,获取数组的长度(容量) | motorPowers.length 返回 4 |
array[index] | 访问指定索引的元素 | motorPowers[0] 返回 50 |
区别
获取长度时,字符串用的是 length() 方法(带括号),而数组用的是 .length 属性(不带括号)。
2.4 常量:不可改变的变量
2.4.1 常量的声明
有时候,我们希望某个值在程序运行期间是固定的、不被允许修改的,比如圆周率 PI 的值。这时,我们就可以使用 final 关键字来定义一个常量。
常量就像一个被锁上的盒子,一旦放入东西,就再也无法更改。
- 声明语法:
final type CONSTANT_NAME = value;(常量名习惯上全大写)
java
/**
* 本程序演示如何使用 final 关键字定义和使用常量。
*/
public class CircleAreaCalculator {
public static void main(String[] args) {
// 使用 final 定义一个名为 PI 的 double 类型常量。
final double PI = 3.14159;
double radius = 5.0;
double area = PI * radius * radius;
System.out.println("半径为 " + radius + " 的圆的面积是: " + area);
}
}1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
2.5 类型转换:杯子里的水
2.5.1 自动类型转换
这就像把小杯子里的水倒进大杯子,非常安全,不会溢出。Java 会自动把范围小、精度低的类型转换成范围大、精度高的类型。
NOTE
char 类型比较特殊,它在运算时会先转换成 int 类型(基于其 ASCII 或 Unicode 值)。
java
int numberOfWheels = 4;
// int 类型的值可以被自动转换后,赋值给 double 类型的变量
double preciseWheels = numberOfWheels; // 自动转换为 double, preciseWheels 的值是 4.0
System.out.println(preciseWheels);1
2
3
4
2
3
4
2.4.2 强制类型转换
这就像把大杯子里的水倒进小杯子,可能会溢出(数据丢失),所以需要你手动确认。
语法:(目标类型) 变量;
java
double batteryVoltage = 12.7;
// double 类型不能自动转为 int,必须强制转换
// 小数部分会被直接舍弃,而不是四舍五入
int approxVoltage = (int) batteryVoltage; // 强制转换,approxVoltage 的值是 12
System.out.println(approxVoltage);
int bigNumber = 200;
// byte 的范围是 -128 到 127,200 超出了范围,会导致数据溢出
byte smallNumber = (byte) bigNumber; // 强制转换,结果会是一个奇怪的负数,因为数据溢出了
System.out.println(smallNumber); // 输出 -561
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
强制转换有风险
强制类型转换可能导致精度丢失(小数部分被截断)或数据溢出(变成一个完全错误的值),使用时必须清楚你正在做什么,并能接受可能带来的后果。
2.6 扩展:基本类型 vs 引用类型
这是 Java 中一个非常重要的概念,它们的根本区别在于存储方式。
基本类型 (Primitive Types):
- 存的是“值”本身。
- 变量的“储物盒”里直接放着
10、3.14、true这些具体数值。 - 当你把一个基本类型变量赋给另一个时,是把值的副本给了对方。
int a = 10; int b = a;// b 得到了 10 这个值,此后 a 和 b 无关。
引用类型 (Reference Types):
- 存的是“地址”(引用)。
- 变量的“储物盒”里放的不是数据本身(比如一个复杂的数组对象),而是这张“通往数据的地图”,即数据在内存中的地址。
- 当你把一个引用类型变量赋给另一个时,是把地址的副本给了对方,两个变量指向了同一个数据对象。
int[] arrA = new int[1]; arrA[0] = 100; int[] arrB = arrA;// arrB 得到了 arrA 的地址,它们都指向同一个数组。此时如果arrB[0] = 99;,那么arrA[0]的值也会变成99!
一个比喻
- 基本类型:你有一张 100 元的钞票,复印一张给朋友,你朋友的钞票是假的,但你的真钞票还在。
- 引用类型:你有一把你家房子的钥匙,你复制一把钥匙给朋友。你们俩现在都可以打开同一扇门,进入同一个房子。你朋友在房子里挂了一幅画,你回家也能看到。
2.7 课堂练习
2.5 课堂练习
练习 1:个人信息卡
任务:
- 声明一个
int类型的变量age,并赋值为你的年龄。 - 声明一个
double类型的变量height,并赋值为你的身高(单位:米)。 - 声明一个
String类型的变量name,并赋值为你的英文名。 - 使用
System.out.println将这些信息组合打印出来,格式为 "My name is [name], I am [age] years old, and my height is [height]m."。
参考答案:
java
/**
* 练习题:声明不同类型的变量并打印个人信息。
*/
public class MyProfile {
public static void main(String[] args) {
// 声明并初始化各个变量
String name = "David";
int age = 15;
double height = 1.72;
// 使用 + 连接字符串和变量,打印出完整信息
System.out.println("My name is " + name + ", I am " + age + " years old, and my height is " + height + "m.");
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
练习 2:圆的周长计算器
任务:
- 声明一个
final的double类型常量PI,赋值为 3.14159。 - 声明一个
double类型的变量radius(半径),并赋值为任意值,例如 6.5。 - 计算圆的周长(公式:
2 * PI * radius),并将结果存入一个新的double变量circumference中。 - 打印出结果,格式为 "A circle with radius [radius] has a circumference of [circumference]."。
参考答案:
java
/**
* 练习题:使用常量和变量计算圆的周长。
*/
public class CircleCircumference {
public static void main(String[] args) {
// 1. 定义 PI 为一个不可变的常量
final double PI = 3.14159;
// 2. 定义一个变量来存储半径
double radius = 6.5;
// 3. 计算周长
double circumference = 2 * PI * radius;
// 4. 打印结果
System.out.println("A circle with radius " + radius + " has a circumference of " + circumference + ".");
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
练习 3:团队成员列表
任务:
- 创建一个长度为 3 的
String数组,名叫teamMembers。 - 把你的三位团队成员的名字分别存入数组的
0,1,2位置。 - 打印出数组的长度。
- 打印出第一位和最后一位团队成员的名字。
