Java 变量、基本数据类型与类型转换

变量是数据的"容器",数据类型决定容器"装什么、装多大、怎么算"。
8 种基本类型是 Java 一切计算的基石;类型转换是写代码时最容易翻车、最隐蔽出 bug 的地方。


一、变量(Variable)

1.1 什么是变量

变量就是内存中的一块命名存储空间,用来保存程序运行中会变化的数据。它是一个"三要素"的组合:

要素 含义 示例
类型 决定存什么、占多大空间 int 占 4 字节
名称 通过名字访问这块空间 age
值 空间里实际存的数据 18
int age = 18;   // 类型 int + 名称 age + 值 18

本质:int age = 18; 这句话做了三件事——在内存中开辟一块 4 字节空间、给空间起名 age、往空间里写入 18。之后 age = 20; 是"改写这块空间的值",而不是"把 age 重新指向别处"(变量不像引用,它本身不"指向",它就是这块空间)。

1.2 变量的使用:三步走

// 第 1 步:声明(只定类型和名字,不赋值)
int age;

// 第 2 步:赋值(把值写进空间)
age = 18;

// 第 3 步:使用(读取 / 参与运算)
System.out.println(age);      // 读取
int next = age + 1;           // 参与运算

// 也可以声明 + 赋值一步到位
int score = 100;

1.3 变量的分类

分类维度 类型 说明
按声明位置 局部变量 方法内部声明,必须初始化才能用,无默认值
按声明位置 成员变量(实例变量/字段) 类内、方法外,有默认值
按修饰符 静态变量(类变量) static 修饰,类加载即存在,全类共享
按数据类型 基本类型变量 存值本身
按数据类型 引用类型变量 存对象的"地址"(如 String、数组、对象)

二、Java 基本数据类型(8 种)

Java 是强类型语言:每个变量必须先声明类型,且类型一旦确定不可更改。基本数据类型(primitive type)共 8 种,分四大类:

2.1 整数型(byte / short / int / long)

类型 占用字节 取值范围 包装类
byte 1 字节(8 位) -128 ~ 127(-2⁷ ~ 2⁷-1) Byte
short 2 字节(16 位) -32768 ~ 32767(-2¹⁵ ~ 2¹⁵-1) Short
int 4 字节(32 位) -2³¹ ~ 2³¹-1(约 ±21 亿) Integer
long 8 字节(64 位) -2⁶³ ~ 2⁶³-1 Long
byte  b = 127;            // ✅ 最大 127
byte  b2 = 128;           // ❌ 编译报错:超出范围
int   i = 2100000000;     // ✅ 约 21 亿
long  l = 3000000000L;    // ✅ 超过 int 范围,必须加 L
long  l2 = 3000000000;    // ❌ 编译报错:整数默认是 int,3000000000 已超 int 范围

2.2 浮点型(float / double)

类型 占用字节 精度 包装类
float 4 字节 单精度,约 6~7 位有效数字 Float
double 8 字节 双精度,约 15~16 位有效数字 Double
double d = 3.14;           // ✅ 浮点数默认是 double
float  f = 3.14F;          // ✅ 必须加 F/f
float  f2 = 3.14;          // ❌ 编译报错:3.14 默认是 double,double 不能自动降为 float

2.3 字符型(char)—— 详见第五节

类型 占用字节 取值范围 包装类
char 2 字节(16 位) 0 ~ 65535(Unicode) Character

2.4 布尔型(boolean)

类型 占用 取值 包装类
boolean 1 字节(JVM 内部实现,规范未明确规定位数) 只有 true / false Boolean
boolean flag = true;
boolean isOk = false;
// boolean b = 1;   // ❌ 不能用 0/1 表示,与 C/C++ 不同

2.5 8 种基本类型总表

类型 大小 默认值 取值范围 包装类
byte 1 字节 0 -128 ~ 127 Byte
short 2 字节 0 -32768 ~ 32767 Short
int 4 字节 0 -2³¹ ~ 2³¹-1 Integer
long 8 字节 0L -2⁶³ ~ 2⁶³-1 Long
float 4 字节 0.0f IEEE 754 单精度 Float
double 8 字节 0.0d IEEE 754 双精度 Double
char 2 字节 '�' 0 ~ 65535 Character
boolean 1 字节 false true / false Boolean

关键区分:上表中的"默认值"指的是成员变量(类字段)的默认值。局部变量没有默认值,不初始化就使用会编译报错。


三、类型定义(字面量的默认类型)

这一节是新手最容易踩坑的地方:你在代码里写的"数字"本身也有类型,Java 对字面量有一组默认规则。

字面量 默认类型 规则
整数(如 100、21) int 整数默认 int
浮点数(如 3.14) double 小数默认 double
long 字面量 加后缀 L/l 推荐大写 L(小写 l 像数字 1)
float 字面量 加后缀 F/f 必须加
十六进制 0x 开头 如 0x1F = 31
八进制 0 开头 如 017 = 15(易混淆,少用)
二进制 0b 开头 如 0b1010 = 10
下划线分隔 1_000_000 数字中间可加 _,增强可读性
long  l1 = 100L;        // ✅ 明确 long
long  l2 = 100;         // ✅ 100 是 int,会自动转 long(安全)
long  l3 = 100_000_000_000L;  // ✅ 超过 int 范围,必须 L
float f1 = 3.14f;       // ✅
double d1 = 3.14;       // ✅ 默认就是 double
double d2 = 3.14d;      // ✅ 加 d 也合法,但没必要
int  hex = 0xFF;        // 255
int  bin = 0b1111;      // 15

一句话口诀:整数默认 int,小数默认 double;long 加 L,float 加 F。


四、变量注意点(高频易错)

  1. 先声明,后使用:Java 不声明类型无法定义变量。

    a = 10;          // ❌ a 未声明
    int a = 10;      // ✅
    
  2. 局部变量必须初始化:不赋初值就使用会编译报错(和成员变量不同)。

    int x;           // 局部变量,未初始化
    System.out.println(x);  // ❌ 编译报错:可能尚未初始化变量 x
    
  3. 变量不能重复声明(同一作用域内同名)。

    int a = 1;
    int a = 2;   // ❌ 重复声明
    
  4. 变量有作用域:从声明处开始,到所在 {} 块结束。

    {
        int a = 1;
    }
    // System.out.println(a);  // ❌ 出了 {} 作用域,a 已失效
    
  5. 类型一旦确定不可更改:不能把 int 变量再赋成字符串。

    int a = 1;
    // a = "hello";   // ❌ 类型不匹配
    
  6. 一行可声明多个同类型变量(但不推荐混不同类型)。

    int a = 1, b = 2, c = 3;   // ✅
    // int a = 1, String s = "x";  // ❌ 类型不同不能同行声明
    
  7. 警惕浮点精度陷阱:float/double 是近似值,不能用 == 判断两个浮点数相等。

    System.out.println(0.1 + 0.2);            // 输出 0.30000000000000004
    System.out.println(0.1 + 0.2 == 0.3);     // false ❗
    // 金融金额计算请用 BigDecimal,不要用 double
    
  8. 整数除法:两个 int 相除,结果仍是 int,会截断小数。

    System.out.println(5 / 2);     // 2,不是 2.5!
    System.out.println(5.0 / 2);   // 2.5,有 double 参与就得到 double
    

五、字符类型(char)

5.1 基本概念

char 是 Java 中唯一的字符类型,占 2 字节,底层用 Unicode 编码,取值范围 0 ~ 65535(对应 Unicode 的 U+0000 ~ U+FFFF)。因为 Java 的 char 采用 UTF-16,所以它能直接表示一个 Unicode 字符(中文、日文、emoji 等基本平面字符都行)。

char c1 = 'A';         // ✅ 单字符,用单引号
char c2 = '中';        // ✅ 中文
char c3 = ' ';         // ✅ 空格也是字符
// char c4 = "A";      // ❌ 双引号是字符串 String,不是 char
// char c5 = 'AB';     // ❌ 只能放单个字符

5.2 char 的三种写法

写法 说明 示例
直接字符 单个字符用单引号 'A'
Unicode 值 \u + 4 位十六进制 'A' = 'A'
转义字符 特殊控制字符 '\n'、'\t'

常用转义字符:

转义符 含义 转义符 含义
\n 换行 \r 回车
\t 制表符(Tab) \\ 反斜杠
\' 单引号 \" 双引号
System.out.println("a\nb");      // 输出两行 a 和 b
System.out.println("a\tb");      // 输出 a	b(中间是 Tab)
char quote = '\'';               // 单引号本身
char backslash = '\\';           // 反斜杠本身

5.3 char 的本质是"整数"

char 底层存的就是 Unicode 码点(一个整数),所以它可以参与整数运算:

char c = 'A';
System.out.println(c + 0);   // 65,即 'A' 的 Unicode 值
System.out.println(c + 1);   // 66
char d = (char)(c + 1);      // 强转回 char,得到 'B'

char z = 'A' + 25;           // 'A'(65) + 25 = 90 = 'Z' ✅ 编译期常量可直接赋给 char

注意:char 参与运算时会被自动提升为 int,运算结果默认是 int,想存回 char 需要强转(见第六节)。

5.4 char vs String(极易混淆)

char String
本质 基本类型(值类型) 引用类型(类)
引号 单引号 'A' 双引号 "A"
长度 固定 1 个字符 0 到多个字符
默认值(成员变量) '�' null
首字母 小写 c 大写 S

六、基本数据类型转换

类型转换分两种:自动类型转换(隐式)和强制类型转换(显式)。核心原则一句话:小范围 → 大范围自动转,大范围 → 小范围要强转。

6.1 自动类型转换(隐式转换)

当小范围类型的值赋给大范围类型时,自动发生,无需任何代码。范围从大到小排序:

byte → short → int → long → float → double
              ↑
             char
int    i = 100;
long   l = i;        // ✅ int → long 自动转
double d = i;        // ✅ int → double 自动转
float  f = 100;      // ✅ int → float 自动转(int 字面量 100)

char c = 'A';
int  n = c;          // ✅ char → int 自动转,n = 65
long lg = c;         // ✅ char → long 自动转

易忽略点:long(8 字节整数)能自动转成 float(4 字节浮点),虽然 float 字节数更少,但浮点数的表示范围比整数大,所以允许。转换顺序是看表示范围,不是单纯看字节数。

6.2 强制类型转换(显式转换)

当大范围类型的值赋给小范围类型时,必须手动强转,语法是 (目标类型)。强转可能造成精度丢失或数据溢出,责任由程序员承担。

double d = 3.99;
int i = (int) d;        // ✅ 强转,i = 3(小数部分被截断,不是四舍五入!)

long l = 100L;
int n = (int) l;        // ✅ long → int 强转

float f = 3.14f;
int m = (int) f;        // 3,同样截断

6.3 转换的四个核心细节

① 整数强转可能溢出(高位截断)

int i = 200;
byte b = (byte) i;      // 结果不是 200,而是 -56!
// 200 的二进制 0000...1100 1000,截成 8 位得 1100 1000,最高位是符号位 → 负数

② 浮点转整数是"截断"而非"四舍五入"

System.out.println((int) 3.99);    // 3,不是 4
System.out.println((int) -3.99);   // -3,向 0 截断

③ byte / short / char 参与运算时,自动提升为 int

byte b1 = 10;
byte b2 = 20;
// byte b3 = b1 + b2;        // ❌ 编译报错:b1 + b2 结果是 int
int  b3 = b1 + b2;           // ✅
byte b4 = (byte)(b1 + b2);   // ✅ 强转回去

这是新手最常见编译错误:两个 byte 相加,结果是 int,不能直接赋回 byte。

④ boolean 不参与任何类型转换

// int x = (int) true;   // ❌ boolean 不能和其他类型互转
// boolean b = 1;        // ❌

6.4 字符串 String 与基本类型的转换(补充)

String 是引用类型,但实际开发中与基本类型互转极常见:

// 基本类型 → String
String s1 = 100 + "";              // 拼接空串
String s2 = String.valueOf(100);   // 推荐
String s3 = Integer.toString(100);

// String → 基本类型(用包装类)
int    i = Integer.parseInt("100");
double d = Double.parseDouble("3.14");
boolean b = Boolean.parseBoolean("true");

// 易错:字符串拼接与数值相加的优先级
System.out.println("a" + 1 + 2);   // a12(从左到右,先拼 "a1",再拼 2)
System.out.println(1 + 2 + "a");   // 3a(先算 1+2=3,再拼 "a")

七、总结

1. 概念三条线:

  • 变量 = 类型 + 名称 + 值,是内存中的命名空间;局部变量必须初始化,成员变量有默认值。
  • 8 种基本类型 = 4 整型(byte/short/int/long)+ 2 浮点(float/double)+ 1 字符(char)+ 1 布尔(boolean)。
  • 类型转换 = 自动(小→大)与强制(大→小,会丢精度/溢出)。

2. 记忆口诀:

  • 类型定义:整数默认 int,小数默认 double,long 加 L,float 加 F。
  • 转换顺序:byte → short → int → long → float → double(char 可并入 int 一路)。
  • 运算提升:byte/short/char 运算先升 int;boolean 不参与转换。

3. 高频坑点清单:

坑点 表现 规避
浮点精度 0.1+0.2 != 0.3 金额用 BigDecimal
整数除法截断 5/2 == 2 至少一个操作数转 double
强转截断 (int)3.99 == 3 明确"截断非四舍五入"
整数溢出 (byte)200 == -56 强转前判断范围
byte 运算提升 byte = byte + byte 报错 结果用 int 或强转
浮点默认 double float f = 3.14 报错 加 F

一句话总结:变量是容器,类型是容器的规格,转换是容器之间"倒水"——大桶倒小桶(自动)水不外溢,小桶倒大桶(强制)可能洒出来。 理解这三点,Java 的类型体系就立住了。


参考:Java 语言规范(JLS)§4.2(基本类型)、《阿里巴巴 Java 开发手册》、官方教程 The Java™ Tutorials - Primitive Data Types

posted @ 2026-08-20 22:05  HuangBingQuan  阅读(6)  评论(0)    收藏  举报