从概念到实战:一文厘清Java中的变量、常量、字段与属性

📅 2026/7/15 16:01:02
从概念到实战:一文厘清Java中的变量、常量、字段与属性
1. 变量与常量的本质区别刚学Java那会儿我最头疼的就是分不清啥时候用变量啥时候用常量。后来发现这俩的区别其实特别简单——变量就像可擦写的白板常量则是用马克笔写的告示牌。比如我们记录用户登录次数int loginCount 0; // 变量 final int MAX_RETRY 3; // 常量这里loginCount会随着用户登录不断增加而MAX_RETRY固定为3次尝试上限。实际项目中我常用final定义配置参数比如数据库连接超时时间final int DB_TIMEOUT 30; // 单位秒关键区别变量可以反复赋值比如loginCount常量赋值后不可修改强行修改会编译报错常量命名规范要求全大写下划线如MAX_VALUE有个坑我踩过以为final修饰的引用类型内容也不可变。其实final ListString只是不能重新赋值但列表内容仍可修改。真要完全不可变得用Collections.unmodifiableList。2. 类变量 vs 成员变量2.1 静态变量的典型场景用static修饰的类变量最适合存全局共享数据。比如统计网站总访问量class Website { static int totalVisits; // 所有实例共享 void visit() { totalVisits; } }我在做电商系统时用静态变量存运费计算规则class Order { static final double SHIPPING_FEE 5.99; // 统一运费 }内存原理类变量存在方法区随类加载而初始化成员变量存在堆内存每个对象独立一份2.2 实例变量的对象特性没有static的就是成员变量也叫实例变量。比如用户对象class User { String name; // 每个用户有自己的名字 int age; }在Spring项目里我常用实例变量存请求相关的状态Controller class PaymentController { Autowired private PaymentService service; // 每个Controller实例有自己的Service }生命周期对比特性类变量成员变量初始化时机类加载时对象实例化时内存位置方法区堆内存访问方式类名.变量名对象.变量名3. 字段(Field)与属性的微妙差异3.1 字段是物理存在字段就是类中声明的变量包括实例变量非static类变量static常量static final比如这个商品类class Product { private long id; // 实例字段 static String category; // 类字段 final String SKU; // 常量字段 }3.2 属性是逻辑概念属性取决于getter/setter方法。这个坑我当年面试就被问过class Employee { private String empName; // 字段 // 属性名为name public String getName() { return empName; } }即使没有name字段只要存在getName()方法就认为有name属性。在Spring MVC中表单绑定就是基于属性而非字段!-- 绑定到name属性而非empName字段 -- input namename value张三4. 内存模型深度解析4.1 变量存储位置用个订单支付的例子说明class Payment { static String BANK ICBC; // 方法区 void process() { double amount 99.9; // 栈内存 Order order new Order(); // 对象在堆 } }存储规则局部变量如amount在栈帧中对象实例如order在堆中静态变量如BANK在方法区常量可能被编译器优化到常量池4.2 生命周期对比通过单例模式看变量生命周期class Singleton { private static Singleton instance; // 类生命周期 private int state; // 对象生命周期 public static Singleton getInstance() { if (instance null) { instance new Singleton(); } return instance; } }instance与类同生共死state随着单例对象创建/销毁而变化5. 实战应用技巧5.1 配置管理方案我推荐这样组织配置常量class AppConfig { // 数据库配置 static final String DB_URL jdbc:mysql://localhost:3306/mydb; static final String DB_USER admin; // 业务规则 static final int MAX_ITEMS 100; // 私有构造防止实例化 private AppConfig() {} }用枚举管理状态码更优雅enum HttpStatus { OK(200), NOT_FOUND(404); private final int code; HttpStatus(int code) { this.code code; } }5.2 线程安全注意事项静态变量要特别注意线程安全class Counter { static int count; // 非线程安全 // 正确写法 static AtomicInteger safeCount new AtomicInteger(); }在Spring中我常用Scope(prototype)避免单例成员变量共享问题。最后说个实用技巧用-Xmx参数控制堆内存时记得方法区元空间默认不受限需要单独配置-XX:MaxMetaspaceSize。曾经有个线上事故就是因为没设这个参数导致内存泄漏。