树码科技 | 技术博客

Java 访问修饰符

2025/12/25
84
0

学习目标

  • 理解 Java 中四种访问修饰符的作用与区别

  • 掌握 private、默认(包私有)、protected 和 public 的使用场景

  • 能够在实际项目中合理运用访问控制以增强封装性和安全性


什么是访问修饰符?

在 Java 中,访问修饰符是用于控制类、方法、变量等成员可见性范围的关键字。它们决定了程序的其他部分能否访问某个特定成员,是实现封装的核心机制之一。

Java 提供了 4 种访问修饰符:

  1. private

  2. 默认(即不写任何修饰符,也称为“包私有”)

  3. protected

  4. public


1. private

  • 关键字:private

  • 作用范围:仅限于声明它的类内部

  • 特点:最严格的访问限制,外部类、子类、甚至同包中的其他类都无法直接访问

class Person {
    // 私有变量
    private String name;

    public void setName(String name) {
        this.name = name; // 类内部可访问
    }

    public String getName() {
        return name; // 类内部可访问
    }
}

public class MainApp {
    public static void main(String[] args) {
        Person p = new Person();
        p.setName("Alice");

        // System.out.println(p.name); // 编译错误:'name' 具有私有访问权限
        System.out.println(p.getName()); // 通过公共方法间接访问
    }
}

输出:

Alice

说明:name 字段被设为 private,强制外部通过 setName() 和 getName() 方法操作数据,这体现了面向对象编程中的数据封装原则。


2. default

默认访问修饰符(包私有)

  • 关键字:无(即不写任何修饰符)

  • 作用范围:同一个包内的所有类均可访问

  • 注意:跨包不可见,即使通过继承也不行

示例:同包访问

// 文件:Car.java(位于默认包或同一命名包中)
class Car {
    String model; // 默认访问权限
}

// 文件:Main.java
public class Main {
    public static void main(String[] args) {
        Car c = new Car();
        c.model = "Tesla"; // 同包内可访问
        System.out.println(c.model);
    }
}

输出:

Tesla

跨包访问失败示例

文件:p1/Tool.java

package p1;

class Tool { // 默认访问修饰符
    void use() {
        System.out.println("Using tool");
    }
}

文件:p2/App.java

package p2;
import p1.*;

class App {
    public static void main(String[] args) {
        Tool t = new Tool(); // ❌ 编译错误!Tool 在 p1 包中是默认访问,p2 无法访问
        t.use();
    }
}

结论:默认修饰符适用于仅在当前包内使用的工具类或辅助方法。


3. protected

  • 关键字:protected

  • 作用范围:

    • 同一个包内的所有类

    • 不同包中的子类(通过继承)

  • 注意:不同包中的非子类不能访问

class Vehicle {
    protected int speed; // 受保护成员
}

class Bike extends Vehicle {
    void setSpeed(int s) {
        speed = s; // 子类中可访问
    }

    int getSpeed() {
        return speed; // 子类中可访问
    }
}

public class Main {
    public static void main(String[] args) {
        Bike b = new Bike();
        b.setSpeed(100);
        System.out.println("通过子类方法访问: " + b.getSpeed());

        Vehicle v = new Vehicle();
        System.out.println(v.speed); // 同包内直接访问(假设 Main 与 Vehicle 同包)
    }
}

输出:

通过子类方法访问: 100
0

关键点:protected 常用于框架设计中,允许用户通过继承扩展功能,同时限制非继承类的随意访问。


4. public

  • 关键字:public

  • 作用范围:整个程序中任意位置均可访问

  • 用途:公开 API、服务类、工具方法等

class MathUtils {
    public static int add(int a, int b) {
        return a + b;
    }
}

public class Main {
    public static void main(String[] args) {
        System.out.println(MathUtils.add(5, 10)); // 任何地方都能调用
    }
}

输出:

15

注意:顶层类(Top-level class)不能声明为 private 或 protected,只能是 public 或默认(包私有)。因为 private 意味着“仅在封闭类中可见”,而顶层类没有外层类。


访问修饰符对比

访问级别

同一类

同一包

不同包子类

不同包非子类

private

✅

❌

❌

❌

默认(包私有)

✅

✅

❌

❌

protected

✅

✅

✅

❌

public

✅

✅

✅

✅


使用建议

修饰符

典型应用场景

private

成员变量、内部辅助方法 —— 尽可能使用,提高封装性

默认(包私有)

包内工具类、测试辅助类、模块内部协作类

protected

框架基类中的可扩展方法(如 Spring、JUnit 中的钩子方法)

public

对外暴露的 API、服务接口、公共工具方法

最佳实践:最小权限原则 —— 总是使用尽可能严格的访问级别。先设为 private,只有在确实需要更广访问时才逐步放宽。


重点总结

  • Java 有 4 种访问修饰符:private、默认、protected、public

  • private 最严格,仅限本类;public 最开放,全局可见

  • 默认修饰符 = 包内可见,常被忽略但非常实用

  • protected = 包内 + 子类可见,是继承体系中的桥梁

  • 顶层类不能是 private 或 protected

  • 合理使用访问修饰符是构建高内聚、低耦合系统的关键


思考题

  1. 为什么 Java 不允许将顶层类声明为 private?请从语言设计角度解释。

  2. 在一个多人协作的大型项目中,如果所有字段都设为 public,会带来哪些潜在风险?

  3. 假设你正在开发一个日志框架,希望用户能继承你的 BaseLogger 类并重写 formatMessage() 方法,但不希望他们直接调用该方法。你会如何设计其访问修饰符?