变量与数据类型
这是什么:变量 = 给数据起的名字,一个贴了名字的盒子,随时存、随时取。
为什么用:上一章我们让电脑说了句话,但它转头就忘——程序还没学会记住数据。没有变量,程序里只能写死数字,改一个值要翻遍整个文件。
如何用:用 = 号赋值就能创建变量,本章把字符串、整数、浮点数、布尔这四种类型都试一遍。
Java 是"强类型"语言
Python 里 age = 18 直接赋值就行;Java 必须先声明类型:
int age = 18;
意思是:"给我一块存整数的空间,取名 age,放进 18"。类型一旦定下,就不能改存别的类型——这就是强类型,啰嗦但严谨,是大项目的安全感来源。
一个变量由三部分组成,写代码时缺一不可:
| 组成 | 例子 | 说明 |
|---|---|---|
| 类型 | int |
决定这块空间多大、能装什么 |
| 名字 | age |
以后就靠它找到这份数据 |
| 值 | 18 |
真正存进去的内容 |
类型定死之后,值可以换,类型不能换:
int age = 18;
age = 19; // ✅ 可以,还是 int,换了个整数值
age = "十九"; // ❌ 编译报错,int 盒子装不下文字
这就是强类型的日常:编译器像个较真的仓库管理员,你存进去的每件货都要先验货。麻烦吗?麻烦。但好处是货不对板永远进不了库,等程序跑起来后,你不用提心吊胆某处突然塞进来一个奇怪的东西。
八大基本类型
Java 有 8 种基本类型,入门先精通最常用的 4 个:
public class TypesDemo {
public static void main(String[] args) {
int age = 18; // 整数
double price = 9.9; // 小数
boolean isVip = true; // 真/假,只有 true 和 false 两个值
char grade = 'A'; // 单个字符,用单引号
System.out.println(age);
System.out.println(price);
System.out.println(isVip);
System.out.println(grade);
}
}
输出:
18
9.9
true
A
| 类型 | 存什么 | 例子 | 占用空间 |
|---|---|---|---|
int |
整数 | int age = 18; |
4 字节 |
double |
小数 | double price = 9.9; |
8 字节 |
boolean |
真 / 假 | boolean isVip = true; |
1 字节 |
char |
单个字符 | char grade = 'A'; |
2 字节(UTF-16) |
剩下 4 个是"更小/更大的盒子":byte、short(小整数)、long(超大整数,赋值结尾加 L)、float(低精度小数,结尾加 f),入门阶段知道有它们就行。
8 个全家福放在这里,混个脸熟即可:
| 类型 | 存什么 | 大小 | 什么时候想起来它 |
|---|---|---|---|
byte |
小整数 | 1 字节 | 处理文件、网络原始数据 |
short |
小整数 | 2 字节 | 少见,几乎不用 |
int |
整数 | 4 字节 | 默认选它 |
long |
大整数 | 8 字节 | int 装不下时(结尾加 L) |
float |
小数 | 4 字节 | 精度要求低(结尾加 f) |
double |
小数 | 8 字节 | 小数默认选它 |
char |
单字符 | 2 字节 | 单个字母/汉字 |
boolean |
真/假 | 1 字节 | 开关、是否 |
再补充一个重要常识——字面量的默认类型。你在代码里直接写出来的值叫字面量:18 这种不带小数点的,Java 一律当 int;9.9 这种带小数点的,一律当 double。所以给 long 赋超大数要加 L、给 float 赋值要加 f,本质都是"告诉 Java:别按默认类型理解我"。
还有个高频角色 String(字符串,如
"你好"):注意首字母大写、用双引号,它不是基本类型而是"对象"。完整玩法在字符串章展开。
类型转换
- 小盒子 → 大盒子(自动):
int转double直接放,不丢信息 - 大盒子 → 小盒子(强制):要加
(类型),可能丢东西
public class CastDemo {
public static void main(String[] args) {
int a = 10;
double b = a; // 自动转换:10 变 10.0
double c = 9.99;
int d = (int) c; // 强制转换:直接砍掉小数,不是四舍五入
System.out.println(b);
System.out.println(d);
}
}
输出:
10.0
9
自动转换有一条固定的"水流方向",水只会从窄河道流向宽河道,反过来就要人工筑坝(强转):
byte → short → int → long → float → double
为什么 int 能自动变 double?因为 8 字节的 double 装下 4 字节的 int 绰绰有余,任何值都不会丢。反过来强转就有风险:9.99 强转成 int 得 9,小数部分直接没了——截断,不是四舍五入,方向是"向零取整"(9.99 和 -9.99 都变成 9 和 -9,把小数尾巴砍向零的方向)。
还有个隐藏规则叫表达式提升:小类型参与运算时,Java 会自动把它们提升成 int 再算。
byte x = 10;
byte y = 20;
byte z = x + y; // ❌ 编译报错:x + y 已经被提升成 int
byte z2 = (byte) (x + y); // ✅ 强转回来才行
记忆方法:byte、short、char 一参与运算,统统先升级成 int。所以 byte + byte 的结果类型是 int,直接塞回 byte 盒子会被拦下。
常量:final 修饰的变量
变量是"值能变"的盒子;如果一个值从头到尾不该变(比如圆周率、最大重试次数),就用 final 把它焊死:
final double PI = 3.14159;
PI = 3.14; // ❌ 编译报错:常量不能再赋值
常量命名用全大写加下划线(如 MAX_SPEED),别人一眼就知道"这是定死的规矩,别打它的主意"。好代码里常量很多、魔法数字(直接写死在逻辑里的 3.14159)很少——都起好名字放前面,改需求时只改一处。
变量命名规范
Java 社区有成文的命名惯例,入门就养成好习惯:
| 东西 | 惯例 | 例子 |
|---|---|---|
| 变量 / 方法 | 小驼峰 | userName、calcBmi |
| 类 | 大驼峰 | HelloWorld、Student |
| 常量 | 全大写下划线 | MAX_TRY、PI |
| 包 | 全小写,域名倒序 | com.example.demo |
"驼峰"指的是单词首字母突起像驼峰:userName 的 U 就是那个"驼"。小驼峰第一个词全小写,大驼峰每个词首字母都大写。
惯例之外还有硬性语法规则(不遵守直接编译报错):
| 规则 | ✅ 合法 | ❌ 非法 |
|---|---|---|
只能由字母、数字、_、$ 组成 |
user_name、$pay |
user-name |
| 不能用数字开头 | score2 |
2score |
| 不能用 Java 关键字 | className |
int、class |
| 区分大小写 | age 和 Age 是两个变量 |
— |
最后一条要划重点:name 和 Name 是两个完全不同的变量,Java 对大小写零容忍。
❓ 常见问题
Q1:int 能存多大的数?
int 是 4 字节,范围大约 -21 亿到 +21 亿。超过这个范围用 long(8 字节,结尾加 L,如 10000000000L)。
Q2:float 和 double 选哪个?
默认用 double。float 精度低,且 Java 里小数字面量默认是 double,给 float 赋值要加 f(如 3.14f),不方便。
Q3:char 只能存英文吗?
不能。char 用 UTF-16 编码,可以存任何 Unicode 字符,包括汉字、emoji:char c = '中';。
Q4:0.1 + 0.2 为什么不等于 0.3?
System.out.println(0.1 + 0.2); // 0.30000000000000004
double 用二进制存小数,而 0.1 在二进制里是无限循环小数,只能存个"近似值",两个近似值一相加,误差就露头了。这是所有语言通病,不是 Java 的 bug。金额计算要避免直接用 double 做精确比较,入门阶段先记住:日常算着玩没问题,涉及钱的精确计算后面有专门方案。
Q5:变量声明了但没赋值,能直接用吗?
局部变量不能。Java 规定局部变量必须先赋值再使用,否则编译报错。这是编译器在保护你:没初始化的内存里是垃圾值,读了它等于闭眼开车。
⚠️ 新手翻车现场
翻车一:double 赋值给 int 直接砍小数
double c = 9.99;
int d = (int) c; // 得到 9,不是 10
问题:强制转换是截断小数(向零取整),不是四舍五入。
修正:想四舍五入用 Math.round(c),返回 long,再转 int:(int) Math.round(9.99) 得 10。
翻车二:char 用双引号
char grade = "A"; // ❌ 编译报错,char 必须单引号
问题:单引号是字符,双引号是字符串。char 必须用单引号 'A'。
修正:char grade = 'A';
翻车三:boolean 用 0/1
boolean isVip = 1; // ❌ 编译报错,Java 没有数字与布尔自动转换
问题:Java 的 boolean 只能是 true 或 false,不能用 0/1 代替。
修正:boolean isVip = true;
翻车四:给 long 赋大数没加 L
long big = 10000000000; // ❌ 编译报错:整数太大
long big2 = 10000000000L; // ✅ 加 L,告诉 Java 这是 long 字面量
问题:整数字面量默认按 int 处理,10000000000 超出了 int 的 21 亿上限,编译器在"理解字面量"这一步就报错了——和左边是什么类型无关。
修正:结尾加 L(建议大写,小写 l 和数字 1 太容易看混)。
翻车五:byte + byte 结果塞不回 byte
byte a = 10;
byte b = 20;
byte c = a + b; // ❌ 编译报错:int 不能转成 byte
问题:表达式提升规则——小类型参与运算先升级成 int,a + b 的结果已经是 int。
修正:byte c = (byte) (a + b); 或者干脆用 int 承接运算结果,省心。
🎯 什么时候用哪种类型
| 场景 | 推荐类型 | 原因 |
|---|---|---|
| 年龄、人数、分数 | int |
整数,范围够用 |
| 身高、体重、价格 | double |
小数,精度高 |
| 是/否、开/关 | boolean |
只有两种状态 |
| 性别 M/F、等级 A | char |
单个字符 |
| 超大整数(如身份证号) | long |
int 装不下 |
| 姓名、地址、消息 | String |
对象,可变长度文本 |
再给你三条选型心法,覆盖表格没列到的情况:
- 整数拿不准就 int,小数拿不准就 double——这两个覆盖 90% 的日常场景。
- 范围可能超预期的计数器用 long——比如播放量、文件字节数,int 看着够,爆款一来就爆。
- "非此即彼"的状态一律 boolean——别用 0/1、别用字符串
"yes",true/false最清晰。
📝 本章小结
- Java 是强类型语言,变量要先声明类型,类型确定后不可变
int整数、double小数、boolean真假、char单字符String是对象,首字母大写、用双引号- 小转大自动,大转小强转并截断小数(不是四舍五入)
- 小类型参与运算会自动提升成
int;整数字面量默认int,小数字面量默认double - 变量命名:小驼峰(变量/方法)、大驼峰(类)、全大写下划线(常量)
- 记忆口诀:变量先报类型;小转大自动,大转小强转还砍尾巴。
记忆锚点:8 种基本类型是一排大小不同的收纳盒——byte/short/int/long 是四档整数盒,float/double 是两档小数盒,char 是单格展示柜,boolean 是只有"开/关"两个档位的电闸。大盒装小物随手放,小盒装大物要强转还得挤一挤。
动手改
- 新增一个变量记录你的身高(米,小数),打印出来
- 把
grade改成"A"(双引号)跑一次,看看编译器怎么说 - 试试
int d = (int) 3.99;——验证是"砍掉"而不是四舍五入 - 用
Math.round(3.5)验证四舍五入的结果 - 声明一个
final常量MAX_SCORE = 100,再尝试给它赋值200,看看编译器如何"执法"
下一章:流程控制,让程序学会做选择 🐸