当前位置: 首页 > article >正文

探索 Java 权限修饰符的奥秘

目录

一、Java 权限修饰符初窥

(一)为啥要有权限修饰符

(二)Java 中的四种权限修饰符

二、private 权限修饰符 —— 私有领域的守护者

(一)private 的访问规则

(二)代码示例

三、default 权限修饰符 —— 默认的默契

(一)default 的访问规则

(二)代码示例

四、protected 权限修饰符 —— 继承中的特权

(一)protected 的访问规则

(二)代码示例

五、public 权限修饰符 —— 开放的大门

(一)public 的访问规则

(二)代码示例

六、权限修饰符的综合运用与最佳实践

(一)数据封装与权限修饰符

(二)继承与权限修饰符的搭配

(三)包的设计与权限修饰符的考虑


宝子们,今天咱们来深入聊聊 Java 中那些看似不起眼,但实则至关重要的权限修饰符。它们就像是一道道关卡,控制着代码的访问范围,决定了哪些部分可以被其他类看到和使用,哪些部分应该隐藏起来。理解好权限修饰符,能让我们写出更安全、更健壮、更易于维护的 Java 代码。

一、Java 权限修饰符初窥

(一)为啥要有权限修饰符

想象一下,你有一个装满宝贝的房间(一个 Java 类),有些宝贝是你愿意和朋友分享的(可以被其他类访问的成员),有些则是非常私人的,只想自己知道(只能在本类中访问的成员)。权限修饰符就像是房间的门锁和窗户的窗帘,帮助你控制谁能看到和触碰这些宝贝。

在一个大型的 Java 项目中,可能有很多不同的类相互协作。如果没有权限修饰符,任何一个类都可以随意访问和修改其他类的成员变量和方法,这将会导致代码的混乱和难以维护。例如,一个表示用户信息的类,其中的密码字段肯定不能被其他随便的类访问和修改,否则用户的信息安全就无法保障了。

(二)Java 中的四种权限修饰符

Java 主要有四种权限修饰符:privatedefault(默认,什么都不写)、protected 和 public。它们从最严格的访问限制到最宽松的访问限制依次排列,每个修饰符都有其特定的适用场景和作用。

二、private 权限修饰符 —— 私有领域的守护者

(一)private 的访问规则

当一个类的成员(变量或方法)被 private 修饰时,它就像是被锁在了一个只有自己能进入的小房间里,只有在这个类的内部才能访问它。其他任何类,无论是同一个包中的类还是不同包中的类,都无法直接访问 private 成员。

(二)代码示例

class BankAccount {
    // 账户余额,使用 private 修饰,确保只有本类可以访问和修改
    private double balance;

    public BankAccount(double initialBalance) {
        this.balance = initialBalance;
    }

    // 存款方法,在本类中操作 balance
    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
            System.out.println("成功存入 " + amount + ",当前余额为 " + balance);
        } else {
            System.out.println("存款金额必须大于 0");
        }
    }

    // 取款方法,同样在本类中操作 balance
    public void withdraw(double amount) {
        if (amount > 0 && amount <= balance) {
            balance -= amount;
            System.out.println("成功取出 " + amount + ",当前余额为 " + balance);
        } else {
            System.out.println("余额不足或取款金额不正确");
        }
    }
}

public class PrivateExample {
    public static void main(String[] args) {
        BankAccount myAccount = new BankAccount(1000);
        myAccount.deposit(500);
        // 以下代码会报错,因为无法在 BankAccount 类外部直接访问 private 变量 balance
        // System.out.println(myAccount.balance);
        myAccount.withdraw(300);
    }
}

在这个例子中,balance 被 private 修饰,所以在 main 方法中无法直接访问它,只能通过 deposit 和 withdraw 方法来间接操作账户余额,这样就保证了余额数据的安全性和完整性,防止了外部的非法访问和修改。

三、default 权限修饰符 —— 默认的默契

(一)default 的访问规则

如果一个类的成员没有使用任何权限修饰符,那么它就具有默认的访问权限(也称为包访问权限)。这意味着这个成员可以被同一个包中的其他类访问,但对于不同包中的类来说,它是不可见的。这种默认的访问权限就像是在一个小圈子里(同一个包)大家默认可以互相分享一些信息,但对于圈子外的人(其他包中的类)则保持神秘。

(二)代码示例

首先创建一个名为 finance 的包,在其中定义两个类:

package finance;

class Budget {
    // 预算金额,使用默认访问权限
    double budgetAmount;

    public Budget(double amount) {
        this.budgetAmount = amount;
    }

    // 计算剩余预算的方法,可供同包中的类使用
    double calculateRemainingBudget(double expense) {
        return budgetAmount - expense;
    }
}

class ExpenseTracker {
    public static void main(String[] args) {
        Budget monthlyBudget = new Budget(5000);
        // 在同包的 ExpenseTracker 类中可以直接访问 Budget 类的 budgetAmount 变量和 calculateRemainingBudget 方法
        double remainingBudget = monthlyBudget.calculateRemainingBudget(2000);
        System.out.println("本月剩余预算:" + remainingBudget);
    }
}

然后在另一个包 outsideFinance 中尝试访问 Budget 类的成员:

package outsideFinance;

import finance.Budget;

public class OutsideAccess {
    public static void main(String[] args) {
        Budget anotherBudget = new Budget(3000);
        // 以下代码会报错,因为在不同包中无法访问 Budget 类的默认权限成员 budgetAmount 和 calculateRemainingBudget 方法
        // double remaining = anotherBudget.calculateRemainingBudget(1000);
        // System.out.println(anotherBudget.budgetAmount);
    }
}

从这个例子可以看出,Budget 类中的 budgetAmount 和 calculateRemainingBudget 方法在 finance 包内可以正常访问和使用,但在 outsideFinance 包中就无法直接访问,这就是 default 权限修饰符的作用。

四、protected 权限修饰符 —— 继承中的特权

(一)protected 的访问规则

protected 修饰符提供了一种在继承关系中更灵活的访问控制。被 protected 修饰的成员可以被同一个包中的其他类访问,就像 default 权限一样。但除此之外,它还可以被不同包中的子类访问和继承。这就像是给家族中的后代(子类)开了一扇特殊的门,让他们能够继承和访问一些祖先(父类)的特定遗产(成员),而对于家族外的人(其他包中的非子类),这些遗产仍然是隐藏的。

(二)代码示例

在 parent 包中定义一个父类:

package parent;

public class Animal {
    // 动物的名字,使用 protected 修饰,以便子类可以访问
    protected String name;

    public Animal(String name) {
        this.name = name;
    }

    // 动物发出声音的方法,使用 protected 修饰,子类可以重写
    protected void makeSound() {
        System.out.println("动物发出声音");
    }
}

在 child 包中定义一个子类继承自 Animal

package child;

import parent.Animal;

public class Dog extends Animal {
    public Dog(String name) {
        super(name);
    }

    // 重写父类的 makeSound 方法
    @Override
    protected void makeSound() {
        System.out.println(name + " 汪汪叫");
    }

    public void showName() {
        // 在子类中可以访问父类的 protected 成员 name
        System.out.println("这只狗的名字是:" + name);
    }
}

然后在 main 方法中测试:

package child;

public class Main {
    public static void main(String[] args) {
        Dog myDog = new Dog("旺财");
        myDog.showName();
        myDog.makeSound();
    }
}

在这个例子中,Animal 类中的 name 和 makeSound 方法被 protected 修饰,Dog 子类可以在不同包中访问和重写这些成员,体现了 protected 修饰符在继承关系中的特殊作用,既保证了一定的封装性,又允许子类进行扩展和定制。

五、public 权限修饰符 —— 开放的大门

(一)public 的访问规则

public 是最宽松的权限修饰符,被 public 修饰的类、成员变量和方法可以被任何其他类访问,无论它们是否在同一个包中。这就像是把东西放在了一个公共的广场上,所有人都可以看到和使用。一般来说,我们会将类的公共接口(其他类需要调用的方法和访问的变量)设置为 public,以便其他类能够方便地与这个类进行交互和协作。

(二)代码示例

public class MathUtils {
    // 一个公共的静态方法,用于计算两个数的和
    public static int add(int num1, int num2) {
        return num1 + num2;
    }
}

public class PublicExample {
    public static void main(String[] args) {
        // 在任何类中都可以直接调用 MathUtils 类的 public 方法 add
        int result = MathUtils.add(5, 3);
        System.out.println("5 + 3 = " + result);
    }
}

在这个例子中,MathUtils 类的 add 方法被 public 修饰,所以在 PublicExample 类中可以直接调用它,即使这两个类可能不在同一个包中。这展示了 public 权限修饰符的开放性和通用性,使得代码的复用和协作变得更加容易。

六、权限修饰符的综合运用与最佳实践

(一)数据封装与权限修饰符

在设计一个类时,我们应该遵循数据封装的原则,将类的成员变量尽可能地用 private 修饰,然后通过 public 的 getter 和 setter 方法来提供对这些变量的访问和修改接口。这样可以隐藏类的内部实现细节,防止外部类的随意访问和修改,提高代码的安全性和可维护性。例如:

public class Person {
    // 私有成员变量,姓名
    private String name;
    // 私有成员变量,年龄
    private int age;

    // 公共的 getter 方法获取姓名
    public String getName() {
        return name;
    }

    // 公共的 setter 方法设置姓名
    public void setName(String name) {
        this.name = name;
    }

    // 公共的 getter 方法获取年龄
    public int getAge() {
        return age;
    }

    // 公共的 setter 方法设置年龄
    public void setAge(int age) {
        if (age > 0) {
            this.age = age;
        } else {
            System.out.println("年龄必须大于 0");
        }
    }
}

在这个 Person 类中,name 和 age 被 private 修饰,外部类只能通过 getNamesetNamegetAge 和 setAge 这些公共方法来与类进行交互,这样就保证了 Person 类的数据安全性和完整性,同时也提供了一定的灵活性,例如在 setAge 方法中可以添加对年龄的合法性验证逻辑。

(二)继承与权限修饰符的搭配

在继承关系中,父类的 private 成员对子类是不可见的,子类无法直接访问和继承。如果希望子类能够访问和扩展父类的某些成员,应该使用 protected 修饰符。同时,父类的公共接口(public 方法)应该设计得足够通用和稳定,以便子类能够在不破坏父类原有功能的基础上进行重写和扩展。例如:

public class Shape {
    // 形状的颜色,使用 protected 修饰,子类可以访问和修改
    protected String color;

    public Shape(String color) {
        this.color = color;
    }

    // 计算面积的抽象方法,子类必须实现
    public abstract double calculateArea();

    // 一个公共的方法,用于打印形状的信息
    public void printInfo() {
        System.out.println("这是一个 " + color + " 的形状");
    }
}

public class Circle extends Shape {
    private double radius;

    public Circle(String color, double radius) {
        super(color);
        this.radius = radius;
    }

    // 实现父类的抽象方法,计算圆的面积
    @Override
    public double calculateArea() {
        return Math.PI * radius * radius;
    }

    // 重写父类的 printInfo 方法,添加圆的半径信息
    @Override
    public void printInfo() {
        super.printInfo();
        System.out.println("它是一个半径为 " + radius + " 的圆,面积为 " + calculateArea());
    }
}

在这个例子中,Shape 类的 color 成员被 protected 修饰,以便 Circle 子类可以访问和使用它来描述圆的颜色。同时,Shape 类定义了公共的抽象方法 calculateArea 和普通方法 printInfo,子类 Circle 可以根据自身的特点实现 calculateArea 方法,并选择性地重写 printInfo 方法,这样既保证了父类的一般性和抽象性,又允许子类进行具体的实现和扩展,体现了继承与权限修饰符之间的良好搭配。

(三)包的设计与权限修饰符的考虑

在设计 Java 项目的包结构时,也应该充分考虑权限修饰符的作用。将相关的类放在同一个包中,并合理地使用 default 权限修饰符,可以使这些类之间的协作更加紧密和自然,同时又对外隐藏了内部的实现细节。而对于需要对外提供公共接口的类和方法,则应该使用 public 修饰符,以便其他包中的类能够方便地使用它们。例如,在一个电商项目中,可能有一个 product 包,其中包含了 Product 类、ProductDao(数据访问对象)类等,这些类在包内通过 default 权限修饰符相互协作,实现对产品数据的增删改查操作,而 Product 类中的一些公共属性和方法,如产品的名称、价格和获取产品详细信息的方法等,则可以使用 public 修饰符,以便其他包中的业务逻辑类能够访问和使用这些信息来进行订单处理、库存管理等操作。

宝子们,Java 的权限修饰符虽然看起来简单,但在实际的编程中却有着深远的影响。通过合理地运用这些权限修饰符,我们可以构建出结构清晰、安全性高、易于维护和扩展的 Java 代码。希望这篇文章能帮助你深入理解和掌握 Java 权限修饰符的奥秘,在今后的编程之旅中更加得心应手!如果在学习过程中有任何疑问或者想要进一步探讨的问题,随时都可以回来看看这篇文章,或者查阅更多的相关资料哦。


http://www.kler.cn/a/457389.html

相关文章:

  • ​​​​​​​CDP集群安全指南系列文章导读
  • 设计模式之桥接设计模式
  • JAVA:利用 Redis 实现每周热评的技术指南
  • 详细的一条SQL语句的执行流程
  • 直播预告丨社区年度交流会 《RTE 和 AI 融合生态洞察报告 2024》发布
  • 《解密奖励函数:引导智能体走向最优策略》
  • C#中相等比较 == 和 Equal函数 对比
  • 在Ubuntu下通过Docker部署Cloudflared Tunnel服务器
  • SpringBoot整合springmvc
  • 遗传算法——附python实现与各方法的作用与修改
  • 【强化学习】深度确定性策略梯度算法(DDPG)详解(附代码)
  • 碰一碰发视频矩阵系统源码搭建,支持OEM
  • Qt仿音乐播放器:QFileDialog添加本地文件
  • BMS存储模块的设计
  • idea 禁用/关闭 sonarlint 后台自动分析(默认开启可能会引起idea卡顿)
  • 【K8s】专题十五(6):Kubernetes 网络之 Pod 网络调试
  • Netty 2024 常见面试题
  • 个人用途虚拟机VM 17安装Ubuntu 16.04.5 图解
  • 大数据面试笔试宝典之Spark面试
  • Java网约车项目实战:实现抢单功能详解
  • golangb并发,Sync包中Mutes,WaitGroup, NewCond的适应
  • 八大排序——直接插入排序
  • 几款性能优秀的差分进化算法DE(SaDE、JADE,SHADE,LSHADE、LSHADE_SPACMA、LSHADE_EpSin)-附Matlab免费代码
  • CAN201 Introduction to Networking(计算机网络)Pt.2 传输层
  • 行为树详解(5)——事件驱动
  • 跨域请求问题