Appearance
12.1 static 静态关键字
static 关键字的概念
static 是 Java 中的一个关键字,用于修饰类、属性、方法和代码块。被 static 修饰的成员属于类,而不属于对象。
static 关键字的用途
1. 静态属性
静态属性(静态变量)是属于类的属性,所有对象共享同一个值。
语法:
java
[访问修饰符] static 数据类型 属性名 [= 初始值];示例:
java
public class Student {
private String name;
private int studentId;
// 静态属性,所有学生共享同一个学校名称
public static String schoolName = "Java University";
public Student(String name, int studentId) {
this.name = name;
this.studentId = studentId;
}
public String getName() {
return name;
}
public int getStudentId() {
return studentId;
}
}
public class StaticExample {
public static void main(String[] args) {
Student student1 = new Student("John", 1001);
Student student2 = new Student("Jane", 1002);
System.out.println(student1.getName() + "'s school: " + Student.schoolName);
System.out.println(student2.getName() + "'s school: " + Student.schoolName);
// 修改静态属性,所有对象都会受到影响
Student.schoolName = "Java Institute";
System.out.println(student1.getName() + "'s school: " + Student.schoolName);
System.out.println(student2.getName() + "'s school: " + Student.schoolName);
}
}2. 静态方法
静态方法是属于类的方法,可以直接通过类名调用,不需要创建对象。
语法:
java
[访问修饰符] static 返回类型 方法名([参数列表]) {
// 方法体
}示例:
java
public class MathUtils {
// 静态方法,计算两个数的和
public static int add(int a, int b) {
return a + b;
}
// 静态方法,计算两个数的差
public static int subtract(int a, int b) {
return a - b;
}
// 静态方法,计算两个数的积
public static int multiply(int a, int b) {
return a * b;
}
// 静态方法,计算两个数的商
public static double divide(int a, int b) {
if (b == 0) {
throw new IllegalArgumentException("除数不能为0");
}
return (double) a / b;
}
}
public class StaticMethodExample {
public static void main(String[] args) {
// 直接通过类名调用静态方法
int sum = MathUtils.add(5, 3);
int difference = MathUtils.subtract(5, 3);
int product = MathUtils.multiply(5, 3);
double quotient = MathUtils.divide(5, 3);
System.out.println("5 + 3 = " + sum);
System.out.println("5 - 3 = " + difference);
System.out.println("5 * 3 = " + product);
System.out.println("5 / 3 = " + quotient);
}
}3. 静态代码块
静态代码块是在类加载时执行的代码块,用于初始化静态属性。
语法:
java
static {
// 静态代码块
}示例:
java
public class StaticBlockExample {
// 静态属性
public static int staticVar;
public static String staticString;
// 静态代码块
static {
System.out.println("静态代码块执行");
staticVar = 100;
staticString = "Hello, static block!";
}
public static void main(String[] args) {
System.out.println("staticVar: " + staticVar);
System.out.println("staticString: " + staticString);
}
}4. 静态内部类
静态内部类是被 static 修饰的内部类,可以直接通过外部类名访问。
示例:
java
public class OuterClass {
private static int outerStaticVar = 100;
private int outerInstanceVar = 200;
// 静态内部类
public static class StaticInnerClass {
private int innerVar = 300;
public void print() {
// 可以访问外部类的静态变量
System.out.println("outerStaticVar: " + outerStaticVar);
// 不能访问外部类的实例变量
// System.out.println("outerInstanceVar: " + outerInstanceVar);
System.out.println("innerVar: " + innerVar);
}
}
public static void main(String[] args) {
// 直接通过外部类名创建静态内部类的对象
OuterClass.StaticInnerClass inner = new OuterClass.StaticInnerClass();
inner.print();
}
}static 关键字的特点
- 属于类:被
static修饰的成员属于类,而不属于对象 - 内存分配:静态成员在类加载时分配内存,只分配一次
- 访问方式:静态成员可以通过类名直接访问,也可以通过对象访问
- 生命周期:静态成员的生命周期与类的生命周期相同
- 不能访问实例成员:静态方法不能直接访问实例属性和实例方法
- 不能使用 this 和 super:静态方法中不能使用
this和super关键字
示例:static 关键字的应用
示例 1:工具类
java
public class StringUtils {
// 私有构造方法,防止创建对象
private StringUtils() {
}
// 静态方法,判断字符串是否为空
public static boolean isEmpty(String str) {
return str == null || str.trim().isEmpty();
}
// 静态方法,反转字符串
public static String reverse(String str) {
if (isEmpty(str)) {
return str;
}
StringBuilder sb = new StringBuilder(str);
return sb.reverse().toString();
}
// 静态方法,截取字符串
public static String substring(String str, int start, int end) {
if (isEmpty(str)) {
return str;
}
if (start < 0) {
start = 0;
}
if (end > str.length()) {
end = str.length();
}
if (start > end) {
return "";
}
return str.substring(start, end);
}
}
public class StringUtilsExample {
public static void main(String[] args) {
String str = "Hello, Java!";
System.out.println("Original string: " + str);
System.out.println("Is empty: " + StringUtils.isEmpty(str));
System.out.println("Reversed: " + StringUtils.reverse(str));
System.out.println("Substring (0, 5): " + StringUtils.substring(str, 0, 5));
}
}示例 2:计数器
java
public class Counter {
// 静态属性,用于计数
private static int count = 0;
// 构造方法,每次创建对象时计数
public Counter() {
count++;
}
// 静态方法,获取计数
public static int getCount() {
return count;
}
// 静态方法,重置计数
public static void resetCount() {
count = 0;
}
}
public class CounterExample {
public static void main(String[] args) {
System.out.println("Initial count: " + Counter.getCount());
// 创建对象
Counter counter1 = new Counter();
System.out.println("After creating counter1: " + Counter.getCount());
Counter counter2 = new Counter();
System.out.println("After creating counter2: " + Counter.getCount());
Counter counter3 = new Counter();
System.out.println("After creating counter3: " + Counter.getCount());
// 重置计数
Counter.resetCount();
System.out.println("After reset: " + Counter.getCount());
}
}示例 3:常量类
java
public class Constants {
// 静态常量
public static final double PI = 3.14159265358979323846;
public static final int MAX_AGE = 150;
public static final int MIN_AGE = 0;
public static final String DEFAULT_NAME = "Unknown";
// 私有构造方法,防止创建对象
private Constants() {
}
}
public class ConstantsExample {
public static void main(String[] args) {
System.out.println("PI: " + Constants.PI);
System.out.println("MAX_AGE: " + Constants.MAX_AGE);
System.out.println("MIN_AGE: " + Constants.MIN_AGE);
System.out.println("DEFAULT_NAME: " + Constants.DEFAULT_NAME);
}
}常见问题
1. 在静态方法中访问实例成员
症状:编译错误:Cannot make a static reference to the non-static field fieldName 或 Cannot make a static reference to the non-static method methodName()
解决方案:静态方法不能直接访问实例属性和实例方法,需要通过对象来访问
示例:
java
public class Example {
private int instanceVar = 10;
private static int staticVar = 20;
// 实例方法
public void instanceMethod() {
System.out.println("instanceVar: " + instanceVar);
System.out.println("staticVar: " + staticVar);
}
// 静态方法
public static void staticMethod() {
// 错误:不能直接访问实例变量
// System.out.println("instanceVar: " + instanceVar);
// 正确:可以访问静态变量
System.out.println("staticVar: " + staticVar);
// 错误:不能直接调用实例方法
// instanceMethod();
// 正确:通过对象调用实例方法
Example example = new Example();
example.instanceMethod();
}
}2. 在静态方法中使用 this 关键字
症状:编译错误:Cannot use this in a static context
解决方案:静态方法中不能使用 this 关键字,因为 this 表示当前对象,而静态方法属于类
示例:
java
public class Example {
private static int staticVar = 10;
// 错误:静态方法中不能使用 this
// public static void staticMethod() {
// System.out.println(this.staticVar);
// }
// 正确:直接访问静态变量
public static void staticMethod() {
System.out.println(staticVar);
}
}3. 静态变量的初始化顺序
症状:静态变量的值不符合预期
解决方案:了解静态变量的初始化顺序:静态变量声明时的初始化 → 静态代码块中的初始化
示例:
java
public class InitializationOrder {
// 静态变量声明时初始化
public static int staticVar1 = 10;
// 静态代码块
static {
staticVar1 = 20;
staticVar2 = 30;
}
// 静态变量声明时初始化
public static int staticVar2 = 40;
public static void main(String[] args) {
System.out.println("staticVar1: " + staticVar1); // 输出 20
System.out.println("staticVar2: " + staticVar2); // 输出 40
}
}最佳实践
工具类使用静态方法:将工具类的方法设为静态,方便直接调用
常量使用静态 final:使用
static final定义常量合理使用静态变量:只在需要共享数据时使用静态变量
静态代码块的使用:用于初始化静态变量,特别是需要复杂初始化的情况
避免在静态方法中访问实例成员:静态方法应该只访问静态成员
私有构造方法:对于只包含静态方法的类,使用私有构造方法防止创建对象
总结
static 关键字是 Java 中的一个重要关键字,用于修饰类、属性、方法和代码块。被 static 修饰的成员属于类,而不属于对象。
static 关键字的主要用途:
- 静态属性:所有对象共享同一个值
- 静态方法:可以直接通过类名调用,不需要创建对象
- 静态代码块:在类加载时执行,用于初始化静态属性
- 静态内部类:可以直接通过外部类名访问
static 关键字的特点:
- 属于类,不属于对象
- 在类加载时分配内存,只分配一次
- 可以通过类名直接访问
- 生命周期与类的生命周期相同
- 不能直接访问实例成员
- 不能使用
this和super关键字
通过合理使用 static 关键字,可以提高代码的效率和可维护性。
