Skip to content

Java 变量类型

变量提供了一个命名的存储空间,程序可以对其进行操作。在 Java 中,每个变量都有一个特定的类型(type),它决定了:

  • 变量内存的大小和布局(layout)。
  • 可以存储的值的范围。
  • 可以对其应用的操作集合。

所有变量在使用前都必须声明。基本语法是:

dataType variableName [= initialValue];
// 或者声明多个相同类型的变量:
dataType var1 [= val1], var2 [= val2], ...;
int count; // 声明一个名为 count 的整型变量
double price = 99.95; // 声明并初始化一个双精度浮点型变量
String name = "Alice"; // 声明并初始化一个 String 对象
boolean isActive = true; // 声明并初始化一个布尔型变量
char grade = 'A'; // 声明并初始化一个字符型变量

Java 根据变量的作用域(scope)和生命周期(lifetime)主要有三种类型的变量:

  • 局部变量(Local Variables)
  • 实例变量(Instance Variables,非静态字段 Non-Static Fields)
  • 类变量(Class Variables,静态字段 Static Fields)
  • 声明: 声明在方法、构造方法或块(例如 if、for、try-catch)内部。
  • 作用域: 仅在其声明的块(方法、构造方法等)内可见。
  • 生命周期: 在进入块时创建,在退出块时销毁。
  • 初始化: 必须在使用前显式初始化。它们没有默认值。
  • 访问修饰符(Access Modifiers): 不能使用访问修饰符(例如 public、private)。
  • 内存: 通常分配在栈(stack)上。
public class LocalVariableDemo {
public void calculateSum() {
int x = 10; // 局部变量 x,已初始化
int y = 20; // 局部变量 y,已初始化
int sum = x + y; // 局部变量 sum,已初始化
System.out.println("Sum is: " + sum);
// int z; // 已声明但未初始化
// System.out.println(z); // 编译时错误:变量 z 可能尚未初始化
}
public void processValue(int value) { // 'value' 是一个局部变量(参数)
if (value > 5) {
String message = "Value is greater than 5"; // message 的作用域仅在 if 块内
System.out.println(message);
}
// System.out.println(message); // 编译时错误:找不到符号 'message'
}
public static void main(String[] args) {
LocalVariableDemo demo = new LocalVariableDemo();
demo.calculateSum();
demo.processValue(10);
}
}

从 Java 10 开始,你可以使用 var 关键字声明局部变量,而无需显式指定类型。编译器会从初始化表达式推断类型。

  • var 只能用于带初始化表达式的局部变量。
  • 不能用于实例/类变量、方法参数或返回类型。
  • 提高了复杂类型的可读性,但应谨慎使用。
public void processData() {
var count = 100; // 推断为 int
var name = "Bob"; // 推断为 String
var prices = new java.util.ArrayList<Double>(); // 推断为 ArrayList<Double>
System.out.println("Count: " + count);
System.out.println("Name: " + name);
prices.add(19.99);
System.out.println("Prices: " + prices);
// var n; // 错误:未初始化变量不能使用 'var'
// var lambda = () -> {}; // 错误:lambda 需要显式目标类型
}
  • 声明: 在类内部、方法、构造方法或块外部声明,不带 static 关键字。
  • 作用域: 对类内的所有方法、构造方法和块可见。根据访问修饰符(public、protected、private、默认)的不同,可以从其他类访问。
  • 生命周期: 使用 new 创建类的对象(实例)时创建。对象被垃圾回收(garbage collected)时销毁。
  • 初始化: 具有默认值(数字为 0,boolean 为 false,对象引用为 null)。可以在声明时或在构造方法中显式初始化。
  • 访问修饰符: 可以使用访问修饰符(public、private、protected、默认)。通常推荐使用 private 来实现封装(encapsulation)。
  • 内存: 作为对象内存的一部分分配在堆(heap)上。
  • 关联: 类的每个对象都有自己的实例变量副本。
public class Product {
// 实例变量
private String productName; // 默认值 null
public double price; // 默认值 0.0
private int stockLevel = 0; // 显式初始化
// 用于初始化实例变量的构造方法
public Product(String name, double price) {
this.productName = name; // 'this' 指代当前对象的变量
this.price = price;
}
public void setStockLevel(int level) {
if (level >= 0) {
this.stockLevel = level;
}
}
public void displayProduct() {
System.out.println("Product: " + this.productName);
System.out.println("Price: " + this.price);
System.out.println("Stock: " + this.stockLevel);
}
public static void main(String[] args) {
Product laptop = new Product("Laptop", 1200.50);
laptop.setStockLevel(50);
Product keyboard = new Product("Keyboard", 75.00);
// keyboard.stockLevel 最初默认为 0
laptop.displayProduct();
System.out.println("---");
keyboard.displayProduct();
// 直接访问公共实例变量(通常不推荐)
System.out.println("Keyboard price: " + keyboard.price);
}
}
  • 声明: 使用 static 关键字在类内部、方法、构造方法或块外部声明。
  • 作用域: 与实例变量在访问修饰符方面类似,但使用类名访问(ClassName.variableName)。
  • 生命周期: 在类由 JVM 加载时创建,在类被卸载时销毁(通常在应用程序终止时)。
  • 初始化: 具有默认值(与实例变量类似)。可以在声明时或在 static 初始化块中初始化。
  • 访问修饰符: 可以使用访问修饰符。
  • 内存: 分配在与类本身关联的特殊内存区域中(通常是堆或 Metaspace 的一部分,具体取决于 JVM 版本),而不是单个对象。
  • 关联: 每个类只有一个副本,由该类的所有对象共享。

常见用途:常量(public static final)以及在所有实例之间共享的计数器。

public class Counter {
// 实例变量:每个对象有自己的计数
private int instanceCount = 0;
// 类变量:在所有 Counter 对象之间共享
private static int totalCount = 0;
// 常量:public, static, final
public static final String DEFAULT_NAME = "Generic Counter";
// 静态初始化块(类加载时运行)
static {
System.out.println("Counter class loaded. Initial totalCount: " + totalCount);
// 可以在这里进行复杂的静态初始化
}
public Counter() {
instanceCount++; // 增加当前对象的计数
totalCount++; // 增加共享的总计数
System.out.println("Counter object created. Instance: " + instanceCount + ", Total: " + totalCount);
}
public int getInstanceCount() {
return this.instanceCount; // 访问实例变量
}
public static int getTotalCount() {
// 不能从静态上下文访问 'this' 或实例变量
// System.out.println(instanceCount); // 错误!
return totalCount; // 访问静态变量
}
public static void main(String[] args) {
System.out.println("Default Name: " + Counter.DEFAULT_NAME); // 访问常量
System.out.println("Initial Total: " + Counter.getTotalCount()); // 访问静态方法
Counter c1 = new Counter();
Counter c2 = new Counter();
Counter c3 = new Counter();
System.out.println("c1 instance count: " + c1.getInstanceCount()); // 应该是 1
System.out.println("c2 instance count: " + c2.getInstanceCount()); // 应该是 1
System.out.println("Final Total Count (via static method): " + Counter.getTotalCount()); // 应该是 3
System.out.println("Final Total Count (via instance c1): " + c1.totalCount); // 可以工作,但不推荐(通过 ClassName 访问)
}
}
  • 在方法或块内部使用局部变量进行临时存储。
  • 使用实例变量存储每个对象特有的状态(属性)。
  • 使用**类变量(静态字段)**作为常量或类所有实例之间共享的数据。