杰瑞科技汇

Java中public static的作用与使用场景?

先理解 public

public 是一个访问修饰符,它决定了类、方法或变量的可见性

Java中public static的作用与使用场景?-图1
(图片来源网络,侵删)
  • 作用:被 public 修饰的成员(类、方法、变量)可以被任何其他类访问,无论这些类位于同一个包中,还是不同的包中。
  • 范围:最大范围的访问权限。
  • 类比:就像一个公开的演讲,任何人都可以进来听。

示例:

// 文件名: Person.java
package com.example;
public class Person {
    public String name; // 公共变量,任何类都可以访问
    public Person(String name) {
        this.name = name;
    }
    public void sayHello() { // 公共方法,任何类都可以调用
        System.out.println("Hello, my name is " + name);
    }
}

任何其他类,即使在不同包里,也可以这样使用 Person 类:

// 文件名: Main.java (可以在另一个包,com.test)
import com.example.Person;
public class Main {
    public static void main(String[] args) {
        Person p = new Person("Alice");
        p.sayHello(); // 可以调用,因为 sayHello() 是 public 的
        System.out.println(p.name); // 可以访问,因为 name 是 public 的
    }
}

再理解 static

static 关键字意味着被修饰的成员(方法或变量)属于类本身,而不是属于该类的任何一个具体对象(实例)

这带来了几个关键点:

Java中public static的作用与使用场景?-图2
(图片来源网络,侵删)

A. 静态变量

  • 特点:一个类的所有实例共享同一个静态变量,它只被分配一次内存,与类一同加载。
  • 用途:用于存储所有对象共享的数据,例如计数器、配置信息等。
  • 如何访问:可以通过 类名.变量名对象名.变量名 来访问,但推荐使用前者。

示例:

public class Counter {
    // 这是一个静态变量,属于 Counter 类,而不是 Counter 的某个实例
    public static int count = 0;
    public Counter() {
        // 每次创建新对象时,共享的 count 会增加
        count++;
    }
}
public class Main {
    public static void main(String[] args) {
        Counter c1 = new Counter(); // count 变为 1
        Counter c2 = new Counter(); // count 变为 2
        Counter c3 = new Counter(); // count 变为 3
        System.out.println(Counter.count); // 推荐方式:通过类名访问,输出 3
        System.out.println(c1.count);     // 也可以通过对象访问,但容易引起误解,输出 3
    }
}

B. 静态方法

  • 特点
    1. 它们只能访问静态变量静态方法
    2. 它们不能访问任何实例相关的成员(非静态变量或方法),因为静态方法在对象被创建之前就已经存在了,它不知道具体是哪个对象在调用它。
  • 用途:通常用于定义与类相关但不依赖于具体对象状态的工具方法,Math.pow(), Arrays.sort() 等。
  • 如何调用:可以通过 类名.方法名() 来调用,无需创建对象。

示例:

public class MathUtils {
    // 静态变量
    public static final double PI = 3.14159;
    // 静态方法,计算圆的面积
    public static double calculateCircleArea(double radius) {
        // 可以访问静态变量 PI
        return PI * radius * radius;
        // 下面这行是错误的,因为 areaCalculator 不是静态的
        // return this.areaCalculator(radius); 
    }
    // 这是一个实例方法,依赖于具体的 MathUtils 对象
    public void areaCalculator(double radius) {
        System.out.println("Instance method called.");
    }
}
public class Main {
    public static void main(String[] args) {
        // 直接通过类名调用静态方法,无需创建 MathUtils 对象
        double area = MathUtils.calculateCircleArea(10.0);
        System.out.println("The area is: " + area); // 输出 The area is: 314.159
        // 调用静态变量
        System.out.println("Value of PI: " + MathUtils.PI); // 输出 Value of PI: 3.14159
    }
}

核心重点:public static 组合在一起

publicstatic 组合在一起时,意思就非常清晰了:

“一个可以被任何地方访问,并且属于类本身,而不是任何对象的方法或变量。”

Java中public static的作用与使用场景?-图3
(图片来源网络,侵删)

public static 变量

这是一个全局变量,可以在整个应用程序中被任何代码直接访问和修改。这通常是一个糟糕的设计,因为它破坏了封装性,使得程序状态难以预测和控制。

不推荐的例子:

public class Config {
    // 这是一个公共静态变量,任何代码都可以修改它,非常危险
    public static boolean DEBUG_MODE = true;
}
public class Logger {
    public void log(String message) {
        if (Config.DEBUG_MODE) { // 直接依赖全局状态
            System.out.println("[DEBUG] " + message);
        }
    }
}
public class Main {
    public static void main(String[] args) {
        Logger logger = new Logger();
        logger.log("This is a debug message."); // 会打印,因为 DEBUG_MODE 是 true
        // 其他任何地方的代码都可以轻易地改变这个状态
        Config.DEBUG_MODE = false; 
        logger.log("This message won't be printed."); // 不会打印
    }
}

更好的做法是使用私有静态变量,并通过公共的静态 getter/setter 方法来控制访问。

public static 方法

这是最常见的用法,通常被称为工具方法辅助方法,它们是功能独立的、不依赖于对象状态的函数。

经典的例子:java.lang.Math

// Math 类的所有方法都是 public static 的
public final class Math {
    public static double abs(double a) { ... }
    public static double max(double a, double b) { ... }
    public static double pow(double a, double b) { ... }
    // ... 等等
}
// 使用时,直接通过类名调用,无需创建 Math 对象
double result = Math.pow(2, 3); // 计算 2 的 3 次方

自定义的 public static 方法示例:

public class StringUtils {
    // 一个公共静态工具方法,检查字符串是否为空或 null
    public static boolean isEmpty(String str) {
        return str == null || str.trim().isEmpty();
    }
}
public class Main {
    public static void main(String[] args) {
        String s1 = "";
        String s2 = "Hello";
        String s3 = null;
        // 直接通过类名调用,非常方便
        System.out.println("Is s1 empty? " + StringUtils.isEmpty(s1)); // true
        System.out.println("Is s2 empty? " + StringUtils.isEmpty(s2)); // false
        System.out.println("Is s3 empty? " + StringUtils.isEmpty(s3)); // true
    }
}

public static void main(String[] args)

这是 Java 程序的入口点,我们必须深刻理解它:

  • public: JVM(Java虚拟机)可以从任何地方调用它来启动程序。
  • static: 在程序启动时,还没有创建任何对象,JVM 需要一个不需要创建实例就能直接调用的方法。static 满足了这一点。
  • void: 这个方法执行完毕后不返回任何值。
  • main: JVM 寻找的特定方法名。
  • String[] args: 命令行参数,允许用户在运行程序时向程序传递数据。

最佳实践和注意事项

  1. 优先使用 private static:如果你需要一个静态变量或方法,但它不应该被外部类直接访问,请始终使用 private static,这是封装原则的体现。

    public class DatabaseConfig {
        // 私有静态变量,通过公共静态方法访问
        private static String dbUrl;
        // 静态初始化块,在类加载时执行一次
        static {
            dbUrl = "jdbc:mysql://localhost:3306/mydb";
        }
        // 公共静态 getter 方法
        public static String getDbUrl() {
            return dbUrl;
        }
    }
  2. 避免 public static 可变状态public static 变量引用的是一个可变对象(如 List, Map),那么它可能会成为线程安全和数据一致性的噩梦,因为任何代码都可以修改这个共享对象。

    // 危险!
    public static List<String> sharedList = new ArrayList<>();

    如果确实需要,请使用不可变对象或提供同步机制。

  3. 静态方法不应依赖可变状态:一个好的静态方法应该是“无状态”的,它的输出只依赖于传入的参数,而不依赖于任何外部会变化的状态,这使它们更易于测试和推理。

  4. 静态导入:如果你在一个类中频繁使用另一个类的静态成员,可以使用 static import 来简化代码,但不要滥用,否则会降低代码的可读性。

    import static java.lang.Math.PI;
    import static java.lang.Math.pow;
    public class Main {
        public static void main(String[] args) {
            double area = pow(5, 2) * PI; // 不用再写 Math.pow 和 Math.PI
            System.out.println(area);
        }
    }
关键字 含义 作用域 生命周期 例子
public 公开的,任何地方可见 任何类 与对象/类相同 public class MyClass
static 静态的,属于类本身 整个类 与类相同(随类加载而创建,随类卸载而销毁) static int count
public static 公开的静态成员,全局可访问的类工具 任何类 与类相同 Math.pow(), public static void main()
  • public 回答了 “谁可以访问?” -> 任何人
  • static 回答了 “它属于谁?” -> 属于类,而不是对象

将它们结合起来,public static 就定义了一套全局可用的、与类绑定的工具函数或共享数据,理解这一点,是迈向 Java 中高级开发的关键一步。

分享:
扫描分享到社交APP
上一篇
下一篇