探索 Java 权限修饰符的奥秘

简介: 本文深入探讨了Java中的权限修饰符

 目录

一、Java 权限修饰符初窥

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

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

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

(一)private 的访问规则

(二)代码示例

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

(一)default 的访问规则

(二)代码示例

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

(一)protected 的访问规则

(二)代码示例

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

(一)public 的访问规则

(二)代码示例

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

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

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

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


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

一、Java 权限修饰符初窥

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

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

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

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

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

二、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);
    }
}

image.gif

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

三、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);
    }
}

image.gif

然后在另一个包 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);
    }
}

image.gif

从这个例子可以看出,Budget 类中的 budgetAmountcalculateRemainingBudget 方法在 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("动物发出声音");
    }
}

image.gif

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);
    }
}

image.gif

然后在 main 方法中测试:

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

image.gif

在这个例子中,Animal 类中的 namemakeSound 方法被 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);
    }
}

image.gif

在这个例子中,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");
        }
    }
}

image.gif

在这个 Person 类中,nameageprivate 修饰,外部类只能通过 getNamesetNamegetAgesetAge 这些公共方法来与类进行交互,这样就保证了 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());
    }
}

image.gif

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

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

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

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

相关文章
|
9月前
|
Java 程序员 数据安全/隐私保护
Java的访问权限
Java的访问权限
119 1
|
9月前
|
安全 Java API
JAVA三种权限认证框架的搭建方法
SaToken、JustAuth和MaxKey是三个用于身份认证和权限管理的工具。SaToken是轻量级框架,简化登录、权限、OAuth2.0等认证,适合中小型项目;JustAuth是第三方授权登录库,支持多种社交平台,易于集成;MaxKey是企业级IAM产品,提供复杂的权限管理和统一认证,支持多种标准协议及社交账号集成。
564 1
|
5月前
|
安全 Java 开发者
Java修饰符与封装:理解访问权限、行为控制与数据隐藏的重要性
Java中的修饰符和封装概念是构建健壯、易维护和扩展的Java应用程序的基石。通过合理利用访问权限修饰符和非访问修饰符,开发者能够设计出更加安全、灵活且高效的代码结构。封装不仅是面向对象编程的核心原则之一,也是提高软件项目质量和可维护性的关键策略。
54 1
|
6月前
|
Java
【Java基础面试三】、说一说你对Java访问权限的了解
这篇文章介绍了Java中的四种访问权限:private、default(无修饰符时的访问权限)、protected和public,以及它们分别在修饰成员变量/方法和类时的不同访问级别和规则。
【Java基础面试三】、说一说你对Java访问权限的了解
|
4月前
|
Java
java中的权限修饰符
java中的权限修饰符
|
6月前
|
前端开发 Java 编译器
【前端学java】类中的访问权限详解,通俗易懂(5)
【8月更文挑战第9天】类中的访问权限详解,通俗易懂(5)
73 0
|
8月前
|
Java 数据安全/隐私保护
Java基础手册二(类和对象 对象创建和使用 面向对象封装性 构造方法与参数传递 this关键字 static关键字 继承 多态 方法覆盖 final关键字 访问控制权限修饰符)
Java基础手册二(类和对象 对象创建和使用 面向对象封装性 构造方法与参数传递 this关键字 static关键字 继承 多态 方法覆盖 final关键字 访问控制权限修饰符)
48 0
|
8月前
|
Java
详解Java中的protected修饰的访问权限
详解Java中的protected修饰的访问权限
|
设计模式 Java 安全
Java中包的作用以及使用、访问权限、单例/多例设计模式、枚举和异常(附带相关面试题)
本章节讲述以下方面知识点 1.包的作用以及使用 2.单例/多例化设计模式 3.枚举 4.访问权限2.异常
105 0
Java中包的作用以及使用、访问权限、单例/多例设计模式、枚举和异常(附带相关面试题)