源本科技 | 码上会

Java 访问修饰符

2025/12/25
57
0

学习目标

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

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

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


什么是访问修饰符?

在 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)不能声明为 privateprotected,只能是 public 或默认(包私有)。因为 private 意味着“仅在封闭类中可见”,而顶层类没有外层类。


访问修饰符对比

访问级别

同一类

同一包

不同包子类

不同包非子类

private

默认(包私有)

protected

public


使用建议

修饰符

典型应用场景

private

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

默认(包私有)

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

protected

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

public

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

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


重点总结

  • Java 有 4 种访问修饰符private、默认、protectedpublic

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

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

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

  • 顶层类不能是 privateprotected

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


思考题

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

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

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