一句话总结:
静态属性和方法就像共享单车,属于整个小区(类),谁(对象)都能用,但骑完记得别乱停(线程安全)!
一、静态属性(Static Fields)——小区公告板
比喻:小区里挂个公告板,所有住户(对象)都能看到并修改,但改的内容会影响所有人。
特点:
- 属于类:用
static修饰,不依赖对象实例。 - 共享数据:所有对象共用同一份数据。
- 内存分配:类加载时分配内存,程序结束时销毁。
代码示例:
class Student {
static String school = "光明小学"; // 静态属性,所有学生共享
String name; // 实例属性,每个学生独有
Student(String name) {
this.name = name;
}
}
public static void main(String[] args) {
Student s1 = new Student("小明");
Student s2 = new Student("小红");
System.out.println(s1.school); // 输出:光明小学
System.out.println(s2.school); // 输出:光明小学
Student.school = "希望小学"; // 直接通过类名修改
System.out.println(s1.school); // 输出:希望小学(所有人受影响!)
}
适用场景:
- 共享配置(如数据库连接参数)。
- 全局计数器(统计对象数量)。
坑点:
- 线程不安全:多个线程同时修改静态属性需加锁(如
synchronized)。 - 内存泄漏:静态属性长期持有大对象不释放。
二、静态方法(Static Methods)——小区公共电话
比喻:小区门口有个公共电话,不用进谁家(创建对象)就能直接打。
特点:
- 直接通过类名调用:如
Math.sqrt(9)。 - 不能访问实例成员:只能操作静态属性和其他静态方法。
代码示例:
class MathUtils {
static double PI = 3.1415926; // 静态属性
// 静态方法:计算圆面积
static double calcCircleArea(double radius) {
return PI * radius * radius;
}
// 错误示例:静态方法访问实例属性
// void printName() {
// System.out.println(name); // 编译错误!name是非静态的
// }
}
public static void main(String[] args) {
double area = MathUtils.calcCircleArea(2.0); // 直接调用
System.out.println(area); // 输出:12.5663704
}
适用场景:
- 工具类方法(如
Arrays.sort())。 - 工厂方法(如
LocalDate.now())。
坑点:
- 无法重写:子类定义同名静态方法只是隐藏父类方法,非多态。
- 滥用导致代码僵化:过度使用静态方法让代码难以扩展和测试。
三、静态代码块(Static Block)——小区物业初始化
比喻:小区交房时,物业统一配置消防设施(只执行一次)。
特点:
- 类加载时自动执行,用于初始化静态属性。
代码示例:
class DatabaseConfig {
static String url;
static String username;
static {
// 模拟读取配置文件
url = "jdbc:mysql://localhost:3306/test";
username = "admin";
System.out.println("数据库配置初始化完成!");
}
}
public static void main(String[] args) {
// 第一次访问类时触发静态代码块
System.out.println(DatabaseConfig.url);
}
// 输出:
// 数据库配置初始化完成!
// jdbc:mysql://localhost:3306/test
四、静态内部类(Static Nested Class)——小区里的独立商铺
比喻:商铺开在小区里,但不属于任何住户(不持有外部类引用)。
特点:
- 不依赖外部类实例:可直接创建
new Outer.Inner()。 - 不能访问外部类非静态成员。
代码示例:
class Outer {
private static String staticMsg = "静态消息";
private String instanceMsg = "实例消息";
static class Inner {
void print() {
System.out.println(staticMsg); // 可以访问外部类静态成员
// System.out.println(instanceMsg); // 编译错误!不能访问非静态成员
}
}
}
public static void main(String[] args) {
Outer.Inner inner = new Outer.Inner(); // 直接创建
inner.print();
}
总结口诀:
“静态属性共享用,静态方法工具人。
静态代码块初始化,静态内部类不依赖。
滥用静态埋大坑,合理使用是灵魂!”