🐸 青蛙编程网
首页 / Java / Java 基础 / 3. 变量与数据类型

变量与数据类型

这是什么:变量 = 给数据起的名字,一个贴了名字的盒子,随时存、随时取。

为什么用:上一章我们让电脑说了句话,但它转头就忘——程序还没学会记住数据。没有变量,程序里只能写死数字,改一个值要翻遍整个文件。

如何用:用 = 号赋值就能创建变量,本章把字符串、整数、浮点数、布尔这四种类型都试一遍。

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 对象,可变长度文本

再给你三条选型心法,覆盖表格没列到的情况:

  1. 整数拿不准就 int,小数拿不准就 double——这两个覆盖 90% 的日常场景。
  2. 范围可能超预期的计数器用 long——比如播放量、文件字节数,int 看着够,爆款一来就爆。
  3. "非此即彼"的状态一律 boolean——别用 0/1、别用字符串 "yes",true/false 最清晰。

📝 本章小结

  • Java 是强类型语言,变量要先声明类型,类型确定后不可变
  • int 整数、double 小数、boolean 真假、char 单字符
  • String 是对象,首字母大写、用双引号
  • 小转大自动,大转小强转并截断小数(不是四舍五入)
  • 小类型参与运算会自动提升成 int;整数字面量默认 int,小数字面量默认 double
  • 变量命名:小驼峰(变量/方法)、大驼峰(类)、全大写下划线(常量)
  • 记忆口诀:变量先报类型;小转大自动,大转小强转还砍尾巴。

记忆锚点:8 种基本类型是一排大小不同的收纳盒——byte/short/int/long 是四档整数盒,float/double 是两档小数盒,char 是单格展示柜,boolean 是只有"开/关"两个档位的电闸。大盒装小物随手放,小盒装大物要强转还得挤一挤。

动手改

  1. 新增一个变量记录你的身高(米,小数),打印出来
  2. 把 grade 改成 "A"(双引号)跑一次,看看编译器怎么说
  3. 试试 int d = (int) 3.99;——验证是"砍掉"而不是四舍五入
  4. 用 Math.round(3.5) 验证四舍五入的结果
  5. 声明一个 final 常量 MAX_SCORE = 100,再尝试给它赋值 200,看看编译器如何"执法"

下一章:流程控制,让程序学会做选择 🐸

📥 下载本章代码

ZIP 内含本章全部代码文件与说明,解压即用,与教程内容同步生成。