Java 权限修饰符(Access Modifiers)指南

📊 权限修饰符总览

修饰符 同类 同包 子类(不同包) 不同包非子类 级别
private 最严格
默认 (无修饰符) 包级别
protected 子类级别
public 最宽松

一般来说小编大多只使用private和public

🎯 四种权限修饰符详解

1. private(私有访问)

特点

  • 只能在本类内部访问
  • 最严格的访问控制
  • 常用于封装,隐藏实现细节

java

typescript 复制代码
package com.example;

public class PrivateDemo {
    // 私有属性 - 只能在本类中访问
    private String secret = "这是机密信息";
    private int privateNumber = 100;
    
    // 私有方法 - 只能在本类中调用
    private void showSecret() {
        System.out.println("机密信息: " + secret);
    }
    
    // 公共方法提供对私有属性的受控访问
    public String getSecret() {
        // 可以添加验证逻辑
        if (checkPermission()) {
            return secret;
        }
        return "无权访问";
    }
    
    public void setSecret(String newSecret) {
        if (validateSecret(newSecret)) {
            this.secret = newSecret;
        }
    }
    
    private boolean checkPermission() {
        // 权限检查逻辑
        return true;
    }
    
    private boolean validateSecret(String secret) {
        // 验证逻辑
        return secret != null && !secret.trim().isEmpty();
    }
    
    // 在本类中可以自由访问私有成员
    public void testAccess() {
        System.out.println("在本类中访问:");
        System.out.println("直接访问私有属性: " + secret);
        System.out.println("调用私有方法: ");
        showSecret();
        
        // 修改私有属性
        privateNumber = 200;
        System.out.println("修改后: " + privateNumber);
    }
    
    public static void main(String[] args) {
        PrivateDemo demo = new PrivateDemo();
        demo.testAccess();
        
        // 通过公共方法访问私有属性
        System.out.println("\n通过公共方法访问:");
        System.out.println("getSecret(): " + demo.getSecret());
        
        demo.setSecret("新的机密");
        System.out.println("修改后: " + demo.getSecret());
        
        // ❌ 错误:不能直接访问私有成员
        // System.out.println(demo.secret);      // 编译错误
        // demo.showSecret();                   // 编译错误
        // demo.privateNumber = 300;            // 编译错误
    }
}

// 同包中的另一个类
class SamePackageClass {
    void test() {
        PrivateDemo demo = new PrivateDemo();
        
        // ❌ 错误:同包其他类也不能访问private成员
        // System.out.println(demo.secret);      // 编译错误
        // demo.showSecret();                   // 编译错误
        
        // ✅ 正确:只能通过公共方法访问
        System.out.println(demo.getSecret());
    }
}

private 在构造器中的应用

java

csharp 复制代码
public class Singleton {
    // 私有静态变量
    private static Singleton instance;
    
    // 私有构造器 - 防止外部创建实例
    private Singleton() {
        System.out.println("Singleton实例被创建");
    }
    
    // 公共静态方法提供访问
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
    
    public void showMessage() {
        System.out.println("Hello Singleton!");
    }
    
    public static void main(String[] args) {
        // ❌ 错误:不能直接new
        // Singleton s = new Singleton();
        
        // ✅ 正确:通过静态方法获取
        Singleton s1 = Singleton.getInstance();
        Singleton s2 = Singleton.getInstance();
        
        System.out.println("s1 == s2: " + (s1 == s2));  // true
        s1.showMessage();
    }
}

2. 默认/包私有(Default/Package-private)

特点

  • 没有明确指定修饰符
  • 同一个包内可以访问
  • 也称为"包访问权限"或"包私有"

java

csharp 复制代码
package com.example;

// 默认类:同包可见
class DefaultClass {
    // 默认属性:同包可见
    String defaultField = "默认属性";
    
    // 默认方法:同包可见
    void defaultMethod() {
        System.out.println("默认方法");
    }
    
    // 公共方法:所有地方可见
    public void publicMethod() {
        System.out.println("公共方法");
    }
}

public class DefaultModifierDemo {
    // 默认属性
    String packagePrivateField = "包私有属性";
    
    // 默认方法
    void packagePrivateMethod() {
        System.out.println("包私有方法");
        System.out.println("可以访问: " + packagePrivateField);
    }
    
    public static void main(String[] args) {
        DefaultModifierDemo demo = new DefaultModifierDemo();
        
        // 在本类中可以访问默认成员
        demo.packagePrivateMethod();
        
        // 在同包中访问另一个类的默认成员
        DefaultClass obj = new DefaultClass();
        System.out.println("\n访问同包的DefaultClass:");
        System.out.println(obj.defaultField);  // ✅ 可以访问
        obj.defaultMethod();                   // ✅ 可以调用
        obj.publicMethod();                    // ✅ 可以调用
    }
}

// 同包中的另一个类
package com.example;

class AnotherClassInSamePackage {
    void test() {
        DefaultModifierDemo demo = new DefaultModifierDemo();
        
        // ✅ 正确:同包可以访问默认成员
        System.out.println(demo.packagePrivateField);
        demo.packagePrivateMethod();
        
        DefaultClass obj = new DefaultClass();
        System.out.println(obj.defaultField);
        obj.defaultMethod();
    }
}

不同包的情况

java

java 复制代码
// 不同包中的类
package other;

import com.example.DefaultModifierDemo;
import com.example.DefaultClass;  // ❌ 编译错误:DefaultClass不是public

public class DifferentPackageClass {
    void test() {
        DefaultModifierDemo demo = new DefaultModifierDemo();
        
        // ❌ 错误:不同包不能访问默认成员
        // System.out.println(demo.packagePrivateField);  // 编译错误
        // demo.packagePrivateMethod();                   // 编译错误
        
        // ✅ 正确:可以访问公共成员
        // demo.publicMethod();  // 如果有的话
        
        // ❌ 错误:不能访问默认类
        // DefaultClass obj = new DefaultClass();  // 编译错误
    }
}

3. protected(受保护访问)

特点

  • 同一个包内可以访问
  • 不同包的子类中可以访问
  • 常用于允许子类访问父类的实现细节

java

csharp 复制代码
package com.base;

public class Parent {
    // protected 属性
    protected String protectedField = "父类的protected属性";
    
    // protected 方法
    protected void protectedMethod() {
        System.out.println("父类的protected方法");
    }
    
    // 默认属性(对比用)
    String defaultField = "父类的默认属性";
    
    // 公共方法
    public void show() {
        System.out.println("在本类中访问:");
        System.out.println("protectedField: " + protectedField);
        System.out.println("defaultField: " + defaultField);
        protectedMethod();
    }
}

// 同包的子类
package com.base;

class SamePackageChild extends Parent {
    public void test() {
        System.out.println("同包子类访问:");
        
        // ✅ 可以访问 protected 成员
        System.out.println("protectedField: " + protectedField);
        protectedMethod();
        
        // ✅ 可以访问默认成员(同包)
        System.out.println("defaultField: " + defaultField);
        
        // 通过 super 访问
        System.out.println("通过super访问: " + super.protectedField);
        super.protectedMethod();
    }
}

// 同包的非子类
package com.base;

class SamePackageNonChild {
    public void test() {
        Parent parent = new Parent();
        
        System.out.println("同包非子类访问:");
        
        // ✅ 可以访问 protected 成员(同包)
        System.out.println("protectedField: " + parent.protectedField);
        parent.protectedMethod();
        
        // ✅ 可以访问默认成员(同包)
        System.out.println("defaultField: " + parent.defaultField);
    }
}

不同包子类的情况

java

java 复制代码
// 不同包的子类
package com.derived;

import com.base.Parent;

public class DifferentPackageChild extends Parent {
    public void test() {
        System.out.println("不同包子类访问:");
        
        // ✅ 可以访问 protected 成员(子类权限)
        System.out.println("protectedField: " + protectedField);
        protectedMethod();
        
        // 通过 super 访问
        System.out.println("通过super访问: " + super.protectedField);
        super.protectedMethod();
        
        // ❌ 错误:不能访问默认成员(不同包)
        // System.out.println(defaultField);  // 编译错误
        
        // ❌ 错误:不能通过父类实例访问 protected 成员
        Parent parent = new Parent();
        // System.out.println(parent.protectedField);  // 编译错误
        // parent.protectedMethod();                   // 编译错误
        
        // ✅ 正确:可以通过自身实例访问
        DifferentPackageChild child = new DifferentPackageChild();
        System.out.println("通过子类实例: " + child.protectedField);
        child.protectedMethod();
    }
}

// 不同包的非子类
package com.derived;

import com.base.Parent;

class DifferentPackageNonChild {
    public void test() {
        Parent parent = new Parent();
        
        System.out.println("不同包非子类访问:");
        
        // ❌ 错误:不能访问 protected 成员
        // System.out.println(parent.protectedField);  // 编译错误
        // parent.protectedMethod();                   // 编译错误
        
        // ❌ 错误:不能访问默认成员
        // System.out.println(parent.defaultField);    // 编译错误
        
        // ✅ 正确:只能访问 public 成员
        parent.show();  // 如果有的话
    }
}

4. public(公共访问)

特点

  • 在任何地方都可以访问
  • 最宽松的访问控制
  • 用于定义对外提供的接口

java

csharp 复制代码
package com.example;

// public 类:所有地方可见
public class PublicDemo {
    // public 属性:所有地方可见
    public String publicField = "公共属性";
    
    // public 方法:所有地方可见
    public void publicMethod() {
        System.out.println("公共方法");
        System.out.println("可以访问: " + publicField);
    }
    
    // 其他权限的方法
    protected void protectedMethod() {
        System.out.println("受保护方法");
    }
    
    void defaultMethod() {
        System.out.println("默认方法");
    }
    
    private void privateMethod() {
        System.out.println("私有方法");
    }
    
    public static void main(String[] args) {
        PublicDemo demo = new PublicDemo();
        
        // 在本类中可以访问所有权限的成员
        demo.publicMethod();
        demo.protectedMethod();
        demo.defaultMethod();
        demo.privateMethod();
    }
}

// 同包的另一个类
package com.example;

class SamePackageClass {
    void test() {
        PublicDemo demo = new PublicDemo();
        
        System.out.println("同包访问:");
        
        // ✅ 可以访问 public 成员
        System.out.println(demo.publicField);
        demo.publicMethod();
        
        // ✅ 可以访问 protected 成员(同包)
        demo.protectedMethod();
        
        // ✅ 可以访问默认成员(同包)
        demo.defaultMethod();
        
        // ❌ 不能访问 private 成员
        // demo.privateMethod();  // 编译错误
    }
}

不同包的情况

java

csharp 复制代码
// 不同包中的类
package other;

import com.example.PublicDemo;

public class DifferentPackageClass {
    void test() {
        PublicDemo demo = new PublicDemo();
        
        System.out.println("不同包访问:");
        
        // ✅ 可以访问 public 成员
        System.out.println(demo.publicField);
        demo.publicMethod();
        
        // ❌ 不能访问 protected 成员(不同包非子类)
        // demo.protectedMethod();  // 编译错误
        
        // ❌ 不能访问默认成员(不同包)
        // demo.defaultMethod();    // 编译错误
        
        // ❌ 不能访问 private 成员
        // demo.privateMethod();    // 编译错误
    }
}

🏗️ 权限修饰符的应用场景

1. 封装:数据隐藏

java

typescript 复制代码
// 银行账户类 - 使用封装保护数据
public class BankAccount {
    // 私有属性:外部不能直接访问
    private String accountNumber;
    private String accountHolder;
    private double balance;
    private String password;
    
    // 公共构造器
    public BankAccount(String accountNumber, String accountHolder, 
                      String password, double initialBalance) {
        this.accountNumber = accountNumber;
        this.accountHolder = accountHolder;
        this.password = password;
        this.balance = initialBalance;
    }
    
    // 公共方法:提供受控的访问
    
    // Getter 方法(只读)
    public String getAccountNumber() {
        return accountNumber;
    }
    
    public String getAccountHolder() {
        return accountHolder;
    }
    
    public double getBalance() {
        return balance;
    }
    
    // 没有 password 的 Getter(安全考虑)
    
    // Setter 方法(有验证)
    public void setAccountHolder(String accountHolder) {
        if (accountHolder != null && !accountHolder.trim().isEmpty()) {
            this.accountHolder = accountHolder;
        }
    }
    
    // 业务方法
    public boolean deposit(double amount) {
        if (amount > 0) {
            balance += amount;
            return true;
        }
        return false;
    }
    
    public boolean withdraw(double amount, String password) {
        if (authenticate(password) && amount > 0 && amount <= balance) {
            balance -= amount;
            return true;
        }
        return false;
    }
    
    // 私有方法:内部使用
    private boolean authenticate(String inputPassword) {
        return this.password.equals(inputPassword);
    }
    
    private void logTransaction(String type, double amount) {
        System.out.println("交易记录: " + type + " $" + amount);
    }
    
    // 受保护方法:给子类扩展用
    protected void applyFee(double fee) {
        if (fee > 0 && balance >= fee) {
            balance -= fee;
        }
    }
    
    public static void main(String[] args) {
        BankAccount account = new BankAccount("123456", "张三", "123456", 1000);
        
        // ✅ 正确:通过公共方法访问
        System.out.println("账户: " + account.getAccountNumber());
        System.out.println("余额: $" + account.getBalance());
        
        account.deposit(500);
        System.out.println("存款后余额: $" + account.getBalance());
        
        boolean success = account.withdraw(200, "123456");
        System.out.println("取款" + (success ? "成功" : "失败"));
        System.out.println("取款后余额: $" + account.getBalance());
        
        // ❌ 错误:不能直接访问私有属性
        // System.out.println(account.balance);      // 编译错误
        // account.balance = 10000;                 // 编译错误
        // System.out.println(account.password);    // 编译错误
    }
}

2. 继承框架设计

java

csharp 复制代码
package framework;

// 框架基类
public abstract class BaseService {
    // 公共方法:对外接口
    public final void execute() {
        initialize();
        process();
        cleanup();
    }
    
    // 受保护方法:子类必须实现或可以重写
    protected abstract void initialize();
    protected abstract void process();
    
    // 受保护方法:子类可以重写
    protected void cleanup() {
        System.out.println("执行清理工作...");
    }
    
    // 私有方法:内部实现细节
    private void log(String message) {
        System.out.println("[LOG] " + message);
    }
    
    // 默认方法:同包的工具方法
    void internalHelper() {
        log("内部辅助方法");
    }
}

// 同包的工具类
package framework;

class ServiceValidator {
    // 默认方法:同包内使用
    static boolean validate(BaseService service) {
        // 可以访问 service.internalHelper()(同包)
        return true;
    }
}

java

typescript 复制代码
// 用户实现类(不同包)
package userapp;

import framework.BaseService;

public class UserService extends BaseService {
    // 实现抽象方法
    @Override
    protected void initialize() {
        System.out.println("用户服务初始化");
    }
    
    @Override
    protected void process() {
        System.out.println("处理用户请求");
    }
    
    // 可以重写 cleanup 方法
    @Override
    protected void cleanup() {
        super.cleanup();  // 调用父类方法
        System.out.println("额外的清理工作");
    }
    
    // 不能访问父类的私有方法
    // private void tryAccess() {
    //     log("测试");  // 编译错误:不能访问父类的private方法
    // }
    
    // 不能访问父类的默认方法(不同包)
    // void tryInternal() {
    //     internalHelper();  // 编译错误:不同包不能访问默认方法
    // }
    
    public static void main(String[] args) {
        UserService service = new UserService();
        service.execute();
    }
}

3. 常量定义

java

arduino 复制代码
// 常量类设计
public final class Constants {
    // 私有构造器:防止实例化
    private Constants() {
        throw new AssertionError("不能实例化常量类");
    }
    
    // 公共常量:所有地方可用
    public static final String APP_NAME = "MyApplication";
    public static final double PI = 3.141592653589793;
    public static final int MAX_RETRY_COUNT = 3;
    
    // 受保护常量:子类可用
    protected static final String DEFAULT_ENCODING = "UTF-8";
    
    // 默认常量:同包可用
    static final String CONFIG_FILE = "app.properties";
    
    // 私有常量:仅本类可用
    private static final String SECRET_KEY = "secret123";
    
    // 公共方法使用常量
    public static String getSecretHash() {
        return hash(SECRET_KEY);  // 可以访问私有常量
    }
    
    private static String hash(String input) {
        // 哈希计算
        return input + "_hashed";
    }
    
    // 同包辅助方法
    static String getConfigPath() {
        return CONFIG_FILE;  // 可以访问默认常量
    }
}

// 使用常量
public class ConstantUsage {
    public static void main(String[] args) {
        System.out.println("应用名称: " + Constants.APP_NAME);
        System.out.println("PI值: " + Constants.PI);
        System.out.println("最大重试次数: " + Constants.MAX_RETRY_COUNT);
        
        // 访问公共方法
        System.out.println("密钥哈希: " + Constants.getSecretHash());
        
        // ❌ 错误:不能访问受保护常量(不是子类)
        // System.out.println(Constants.DEFAULT_ENCODING);
        
        // ❌ 错误:不能访问默认常量(不同包)
        // System.out.println(Constants.CONFIG_FILE);
        
        // ❌ 错误:不能访问私有常量
        // System.out.println(Constants.SECRET_KEY);
    }
}

⚠️ 权限修饰符的注意事项

1. 类级别的访问控制

java

csharp 复制代码
// 公共类:所有地方可见(文件名必须与类名相同)
public class PublicClass {
    public void show() {
        System.out.println("公共类");
    }
}

// 默认类:同包可见
class DefaultClass {
    void show() {
        System.out.println("默认类");
    }
}

// 错误:一个文件只能有一个公共类,且必须与文件名相同
/*
public class AnotherPublicClass {  // 编译错误
}
*/

// 内部类可以是任何访问级别
class Outer {
    public class PublicInner {}
    protected class ProtectedInner {}
    class DefaultInner {}
    private class PrivateInner {}
}

// 测试
public class ClassLevelAccess {
    public static void main(String[] args) {
        PublicClass pc = new PublicClass();
        pc.show();
        
        // 同包可以访问默认类
        DefaultClass dc = new DefaultClass();
        dc.show();
        
        System.out.println("\n类访问规则:");
        System.out.println("1. 一个.java文件只能有一个public类");
        System.out.println("2. public类名必须与文件名相同");
        System.out.println("3. 可以有多个默认类");
        System.out.println("4. 内部类可以是任何访问级别");
    }
}

2. 接口成员的访问权限

java

csharp 复制代码
// 接口中的成员默认都是 public
public interface MyInterface {
    // 常量默认是 public static final
    String CONSTANT = "接口常量";  // 等价于 public static final
    
    // 方法默认是 public abstract
    void doSomething();  // 等价于 public abstract void doSomething()
    
    // Java 8+:默认方法
    default void defaultMethod() {
        System.out.println("默认方法");
    }
    
    // Java 8+:静态方法
    static void staticMethod() {
        System.out.println("静态方法");
    }
    
    // ❌ 错误:不能使用private(Java 9+可以)
    // private void privateMethod();  // Java 8编译错误
    
    // ❌ 错误:不能使用protected
    // protected void protectedMethod();  // 编译错误
}

// 实现接口
class MyImplementation implements MyInterface {
    // 必须使用public重写(不能更严格)
    @Override
    public void doSomething() {
        System.out.println("实现接口方法");
    }
    
    // 可以重写默认方法(可选)
    @Override
    public void defaultMethod() {
        MyInterface.super.defaultMethod();  // 调用接口的默认方法
        System.out.println("重写的默认方法");
    }
}

public class InterfaceAccess {
    public static void main(String[] args) {
        MyInterface.staticMethod();  // 调用接口静态方法
        
        MyImplementation impl = new MyImplementation();
        impl.doSomething();
        impl.defaultMethod();
        
        System.out.println("常量: " + MyInterface.CONSTANT);
    }
}

3. 构造器的访问权限

java

csharp 复制代码
public class ConstructorAccess {
    // 公共构造器:所有地方可以创建对象
    public ConstructorAccess() {
        System.out.println("公共构造器");
    }
    
    // 受保护构造器:同包或子类可以创建对象
    protected ConstructorAccess(int a) {
        System.out.println("受保护构造器: " + a);
    }
    
    // 默认构造器:同包可以创建对象
    ConstructorAccess(String s) {
        System.out.println("默认构造器: " + s);
    }
    
    // 私有构造器:只能在本类中创建对象
    private ConstructorAccess(boolean b) {
        System.out.println("私有构造器: " + b);
    }
    
    // 静态工厂方法访问私有构造器
    public static ConstructorAccess createPrivateInstance() {
        return new ConstructorAccess(true);
    }
    
    public static void main(String[] args) {
        // 本类中可以访问所有构造器
        new ConstructorAccess();           // public
        new ConstructorAccess(10);         // protected
        new ConstructorAccess("test");     // default
        new ConstructorAccess(true);       // private
        
        // 工厂方法
        ConstructorAccess.createPrivateInstance();
    }
}

// 同包的其他类
class SamePackageClass {
    void test() {
        new ConstructorAccess();           // ✅ public
        new ConstructorAccess(20);         // ✅ protected(同包)
        new ConstructorAccess("hello");    // ✅ default(同包)
        // new ConstructorAccess(true);    // ❌ private
    }
}

// 不同包子类
package other;

import ConstructorAccess;

class DifferentPackageChild extends ConstructorAccess {
    public DifferentPackageChild() {
        super(30);  // ✅ 可以调用protected构造器(子类)
        // super("test");  // ❌ 不能调用default构造器(不同包)
    }
    
    void test() {
        // new ConstructorAccess(40);  // ❌ 不能直接调用(需要是子类构造器中)
    }
}

// 不同包非子类
package other;

import ConstructorAccess;

class DifferentPackageNonChild {
    void test() {
        new ConstructorAccess();           // ✅ public
        // new ConstructorAccess(50);      // ❌ protected
        // new ConstructorAccess("test");  // ❌ default
        // new ConstructorAccess(true);    // ❌ private
    }
}

💡 权限修饰符最佳实践

1. 最小权限原则

java

typescript 复制代码
// 遵循最小权限原则:只暴露必要的内容
public class Employee {
    // 私有属性:隐藏实现细节
    private String id;
    private String name;
    private double salary;
    private String ssn;  // 社保号(敏感信息)
    
    // 公共构造器:允许创建对象
    public Employee(String id, String name) {
        this.id = id;
        this.name = name;
        this.salary = 0.0;
    }
    
    // 公共getter:只读访问
    public String getId() {
        return id;
    }
    
    public String getName() {
        return name;
    }
    
    public double getSalary() {
        return salary;
    }
    
    // 受保护setter:允许子类或同包修改
    protected void setSalary(double salary) {
        if (salary >= 0) {
            this.salary = salary;
        }
    }
    
    // 默认方法:同包工具方法
    void internalUpdate(String newName) {
        if (newName != null && newName.length() >= 2) {
            this.name = newName;
        }
    }
    
    // 私有方法:内部逻辑
    private void calculateBonus() {
        // 奖金计算逻辑
    }
    
    // 没有提供ssn的getter/setter(安全考虑)
}

// 管理者类(需要修改工资)
class Manager extends Employee {
    public Manager(String id, String name) {
        super(id, name);
    }
    
    public void adjustSalary(Employee emp, double newSalary) {
        // 可以调用受保护方法
        emp.setSalary(newSalary);
    }
}

2. 模块化设计

java

java 复制代码
// 包结构示例:
// com.company
//   ├── api          (公共API)
//   ├── impl         (实现,包私有)
//   ├── internal     (内部实现,包私有)
//   └── util         (工具类)

// api包:公共接口
package com.company.api;

public interface UserService {
    User getUser(String id);
    void saveUser(User user);
}

// impl包:实现(包私有)
package com.company.impl;

import com.company.api.UserService;
import com.company.internal.UserValidator;

class UserServiceImpl implements UserService {
    private UserValidator validator = new UserValidator();
    
    @Override
    public User getUser(String id) {
        // 实现...
        return null;
    }
    
    @Override
    public void saveUser(User user) {
        if (validator.validate(user)) {
            // 保存逻辑
        }
    }
}

// internal包:内部工具(包私有)
package com.company.internal;

class UserValidator {
    boolean validate(User user) {
        // 验证逻辑
        return true;
    }
}

// 公共工厂
package com.company;

import com.company.api.UserService;
import com.company.impl.UserServiceImpl;

public class ServiceFactory {
    // 公共方法返回接口类型,隐藏实现
    public static UserService createUserService() {
        return new UserServiceImpl();
    }
}

📊 权限修饰符选择指南

选择流程图

text

arduino 复制代码
开始
  ↓
需要从外部访问吗?
  ├─ 否 → 使用 private
  ↓
需要被子类访问吗?
  ├─ 否 → 需要同包访问吗?
  │      ├─ 是 → 使用 默认
  │      ↓
  │     否 → 使用 public
  ↓
是 → 需要不同包子类访问吗?
        ├─ 是 → 使用 protected
        ↓
       否 → 使用 默认

决策表格

场景 推荐修饰符 示例
数据字段 private private String name;
常量 public static final public static final PI = 3.14;
工具方法 private private void validate()
模板方法 protected protected void initialize()
接口方法 public public void save()
构造器 public / private public User() / 单例模式
内部类 private private class Node
测试钩子 protected protected void setUp()

🎓 总结要点

  1. private:严格封装,仅本类可见
  2. 默认:包级别封装,同包可见
  3. protected:继承友好,同包+子类可见
  4. public:完全开放,所有地方可见

核心原则

  • 最小权限原则:只开放必要的访问权限
  • 封装变化:使用private隐藏实现细节
  • 面向接口:通过public方法提供稳定接口
  • 继承设计:protected用于设计可扩展的框架
  • 包组织:合理使用包和默认权限管理模块

记住:良好的访问控制是高质量代码的基础!合理的权限设置可以提高代码的安全性、可维护性和可扩展性。

相关推荐
马卡巴卡几秒前
Java线程协作工具:CountDownLatch 、CyclicBarrier、Phaser、Semaphore 、Exchanger
后端
Java水解6 分钟前
Spring Bean生命周期深度剖析:从创建到销毁的完整旅程
spring boot·后端
Json_10 分钟前
springboot框架对接物联网,配置TCP协议依赖,与设备通信,让TCP变的如此简单
java·后端·tcp/ip
+VX:Fegn089515 分钟前
计算机毕业设计|基于springboot + vue职位管理推荐系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
王中阳Go15 分钟前
06 Go Eino AI应用开发实战 | Eino 框架核心架构
人工智能·后端·go
Angletank19 分钟前
SpringBoot用JPA接口实现分页和排序
windows·spring boot·后端
疯狂的程序猴20 分钟前
生成加密 IPA 的工具在项目中的使用方式
后端
华仔啊29 分钟前
Java 开发必看:什么时候用 for,什么时候用 Stream?
java·后端
程序员岳焱37 分钟前
2025 IDEA运行报错:运行 xxxxApplication 时出错。命令行过长。 通过 JAR 清单或通过类路径文件缩短命令行,然后重新运行。
后端·intellij idea
Psycho_MrZhang1 小时前
Flask 设计思想总结
后端·python·flask