第 2 章 / 共 20 章
变量、基本类型与字面量
8 种基本类型、包装类、var 推断、final 常量、装箱陷阱
8 种基本类型(primitive)
Java 区分基本类型和引用类型。基本类型直接存值、没有方法、有固定字节宽度;引用类型是对象,存的是地址。
类型 字节 默认值 范围
-------- ---- -------- --------------------------
byte 1 0 -128 ~ 127
short 2 0 -32768 ~ 32767
int 4 0 约 ±21 亿
long 8 0L 约 ±9.2×10^18
float 4 0.0f 单精度浮点
double 8 0.0d 双精度浮点
char 2 '\u0000' 一个 UTF-16 单元(0 ~ 65535)
boolean 1* false true / false(*JVM 实现而定)声明与赋值
// Vars.java
public class Vars {
public static void main(String[] args) {
int age = 30;
double price = 19.9;
char letter = 'A';
boolean ok = true;
String name = "Alice"; // 引用类型
// 多变量同时声明
int x = 1, y = 2, z = 3;
System.out.println(age + " " + price + " " + letter + " " + ok);
System.out.println(name + " " + x + " " + y + " " + z);
}
}字面量与下划线分隔
数字字面量可以带类型后缀(L / f / d),整数支持二进制 0b、八进制 0、十六进制 0x 前缀。Java 7+ 允许下划线提升可读性(不影响值)。
// Literals.java
public class Literals {
public static void main(String[] args) {
long big = 10_000_000_000L; // 必须 L 后缀(默认 int 装不下)
float pi = 3.14f; // float 必须 f 后缀
double d = 1.0; // 默认 double,d 后缀可省
int hex = 0xFF; // 255
int oct = 010; // 8
int bin = 0b1010; // 10
int million = 1_000_000;
System.out.println(big);
System.out.println(pi);
System.out.println(d);
System.out.println(hex + " " + oct + " " + bin + " " + million);
}
}包装类与自动装箱
8 种基本类型各有一个对应的包装类(Integer、Long、Double、Boolean…)。引用类型的集合(如 List<Integer>)必须用包装类,编译器自动在基本类型和包装类之间转换,称为"自动装箱 / 拆箱"。
// Boxing.java
import java.util.ArrayList;
import java.util.List;
public class Boxing {
public static void main(String[] args) {
Integer boxed = 42; // 自动装箱:int -> Integer
int unboxed = boxed; // 自动拆箱:Integer -> int
List<Integer> nums = new ArrayList<>();
nums.add(1); // 自动装箱
nums.add(2);
int sum = 0;
for (Integer n : nums) {
sum += n; // 自动拆箱
}
System.out.println(sum); // 3
}
}// BoxingTrap.java
public class BoxingTrap {
public static void main(String[] args) {
Integer a = 100, b = 100;
Integer c = 200, d = 200;
System.out.println(a == b); // true (在缓存范围)
System.out.println(c == d); // false(超出缓存)
System.out.println(c.equals(d)); // true (正确做法)
}
}var 局部变量推断(Java 10+)
var 只能用于局部变量,编译器从右侧字面量推断类型。不是动态类型——类型仍然在编译期确定。
// Var.java
import java.util.ArrayList;
public class Var {
public static void main(String[] args) {
var count = 0; // int
var name = "Alice"; // String
var list = new ArrayList<Integer>(); // ArrayList<Integer>
list.add(1);
list.add(2);
System.out.println(count + " " + name + " " + list);
}
// var 不能用于字段、方法参数、方法返回值
// private var bad; // 编译错误
// void f(var x) {} // 编译错误
}final 常量
final 修饰变量后只能赋一次值。习惯上常量名全大写、下划线分隔。
// Constants.java
public class Constants {
static final double PI = 3.141592653589793;
static final String APP_NAME = "VelToolKit";
public static void main(String[] args) {
final int max = 100;
// max = 200; // 编译错误:cannot assign a value to final variable
System.out.println(PI + " " + APP_NAME + " " + max);
}
}类型转换
小范围 → 大范围自动转换(widening),反过来必须强制 (cast)(narrowing),可能丢失精度。
// Cast.java
public class Cast {
public static void main(String[] args) {
int i = 100;
long l = i; // 自动 widening
double d = i; // int -> double 自动
double pi = 3.14;
int truncated = (int) pi; // 强制转换,丢小数:3
long big = 10_000_000_000L;
int overflow = (int) big; // 溢出:1410065408
System.out.println(l + " " + d + " " + truncated + " " + overflow);
}
}== vs equals 陷阱
== 比较基本类型是值比较;比较引用类型是"是不是同一对象"。比较字符串/包装类等内容是否相等,永远用 .equals()。
// EqualsTrap.java
public class EqualsTrap {
public static void main(String[] args) {
String a = "hello";
String b = "hello"; // 字符串字面量池,同一对象
String c = new String("hello"); // 显式 new,新对象
System.out.println(a == b); // true(同一池对象)
System.out.println(a == c); // false(不同对象)
System.out.println(a.equals(c)); // true(内容相同,正确)
}
}