从源码学习访问控制符使用

从源码学习访问控制符使用

Java中的访问控制符

​ 在Java中,有四个访问控制符:public、protected、default(默认或缺省,不使用关键字)和private。

​ 它们的访问范围如下:

  1. public:公共访问权限,具有最宽松的访问权限。可以被任何类访问,无论是否在同一个包中。
  2. protected:受保护的访问权限。可以在同一个包中的其他类中被访问,以及在不同包的子类中访问。但是,它不能被同一个包中的非子类类访问。
  3. default:默认的访问权限,没有使用任何关键字。包级访问权限,只能在同一个包中的其他类中访问。
  4. private:私有的访问权限,具有最严格的访问权限。只能在定义它的类中访问,其他任何类都无法访问。

​ 下面是四个访问控制符的访问范围总结:

访问控制符 同一个类 同一个包 不同包的子类 不同包的非子类
public Yes Yes Yes Yes
protected Yes Yes Yes No
default Yes Yes No No
private Yes No No No

​ 通过合理使用访问控制符,可以控制类、方法、变量等成员的访问权限,从而提高代码的封装性和安全性。

​ 访问控制符,可以用来修饰类、方法和变量。使用不同的控制符,可以达到不同的权限控制效果。

​ 根据迪米特法则,也即最少知道原则,我们应该尽可能少的暴露内部细节,只需要暴露需要对外暴露的部分,已提高封装性和安全性。接下来就从源码层面,看下访问控制符是如何实际使用。

修饰类

  • public修饰的类,是公共类,不同包下可以访问的类,也是最常见的类修饰符。比如Collections类,需要它的时候,我们随时都可以访问到。

    从源码学习访问控制符使用_第1张图片

  • protected修饰符不能直接用于类。(内部类允许但很少用)

  • default修饰的类,具有包级访问权限,可以用来限定此类只在本包内使用。

    从源码学习访问控制符使用_第2张图片

    如SignedMutableBigInteger类,它就使用了缺省的控制符,它只在包内被使用。具体到default修饰的类的场景,有以下的情况

    1. 封装性:可以隐藏其实现细节,只对同一个包内的其他类可见。这种封装性可以防止其他包的类直接访问该类,从而保护类的内部状态和行为。

    2. 模块化和组织:可以帮助开发者将相关的类组织在同一个包内,使得代码更加清晰和易于维护。

    3. API设计:有时候某个类的功能仅适用于同一个包内的其他类,不适合对外公开。这样的类可以被声明为包级访问权限,以避免误用和滥用。

  • private修饰符不能直接用于类。但可以用来修饰内部类,表示此内部类仅能在此类中使用。

    从源码学习访问控制符使用_第3张图片

    比如Hashtable中的EntrySet类,就是被private修饰的内部类。通常一个类被设计为private修饰的内部类,往往有以下考虑:

    ​ 可以实现封装和隐藏内部细节,提高代码的可维护性和安全性。

修饰方法

  • public修饰方法,表示是公开的方法,不同包下可以调用到此方法,这也是最常见的方法修饰符

    从源码学习访问控制符使用_第4张图片

  • protected修饰的方法,可以被包内访问,同时也可以被包外的子类访问。提供了一种介于公共访问和私有访问之间的访问级别。在继承、封装和包内访问等场景下起到了重要的作用,帮助实现类的继承、封装和扩展。

    从源码学习访问控制符使用_第5张图片

    例如AbstractList的removeRange方法就满足上述用法。

    当一个方法被protected修饰时,通常是基于以下场景:

    1. 继承和重写:protected修饰的方法可以被子类继承和重写。这样可以在子类中对父类方法进行自定义实现,扩展或修改其行为。

    2. 子类调用:protected修饰的方法可以在父类中调用,同时也可以在子类中通过super关键字调用。这使得父类可以在特定情况下,控制子类对方法的访问权限,提供更加灵活的设计和实现。

  • default修饰的方法,可在同一个包中的其他类中访问。

    它限制了方法的访问范围,只允许同一个包中的类使用该方法,提高了类的封装性和安全性。

    同时,这些方法也没有被声明为public,避免了对外部类的不必要暴露。

    从源码学习访问控制符使用_第6张图片

  • private修饰的方法,只能在当前类中被使用。

    1. 比较常用的是视为是内部方法,不对外暴露。

      从源码学习访问控制符使用_第7张图片

      ​ 比如LinkedHashMap的一个private修饰的方法,就只在其内部调用使用,隐藏了内部细节,没有对外暴露。

    2. 当一个构造方法被private修饰时,可以确保类示例不可对外通过new的创建,这可以用来实现单例模式或工厂模式等。

      从源码学习访问控制符使用_第8张图片

      ​ 比如DirectMethodHandle类,就是将其构造方法私有化,然后通过静态的外部接口来获取示例,来实现工厂模式。

    3. 还有工具类或者辅助类也使用private修饰构造方法。这些类不需要实例化对象,只提供静态方法或者静态字段来完成特定的功能。

      从源码学习访问控制符使用_第9张图片

      ​ 比如Math就是一个工具类,它将构造方法私有,然后通过静态方法提供所需的功能。

修饰变量

  • public修饰的变量可以被任何类访问。当需要将变量暴露给外部类或其他模块使用时,可以使用public修饰。

    ​ public修饰的变量通常用于定义常量,以供其他类直接使用。常量在Java中通常使用static final修饰,例如公共的静态常量。

    从源码学习访问控制符使用_第10张图片

    ​ 比如Math类中的常量E和PI,用public修饰,可以供外部直接调用。

    ​ 需要注意的是,公共变量的可见性较高,可以被任何类直接访问和修改。这可能导致类的内部状态被不合理地修改,破坏了封装性。

    ​ 因此,在设计和使用公共变量时,需要慎重考虑其对类的封装性和安全性的影响。建议在设计类时,尽量使用私有变量,并提供公共的访问方法(getter和setter)来控制对变量的访问和修改。

  • protected修饰的变量,一般是为了给继承类提供一些内部数据结构或状态的访问权限,而不是直接暴露给外部使用。

    因此,在使用这些变量时,仍然需要遵循面向对象的封装原则,尽量减少直接访问这些变量的场景,而是通过提供合适的方法来进行操作。

    从源码学习访问控制符使用_第11张图片

    例如Calendar的time字段,它被protected修饰,是为了方便继承类访问和修改日历的时间。

  • default较少用来修饰变量。

    ​ 一些使用了默认修饰符,但它们通常被声明为transient(瞬态),表示它们在序列化过程中将被忽略。这是因为在序列化过程中,只有具有public或private修饰符的变量才会被序列化和反序列化。

    从源码学习访问控制符使用_第12张图片

    ​ 其次,还有一些常量,使用了默认修饰符,用来表示可在同一个包下访问此静态常量。从源码学习访问控制符使用_第13张图片

  • private修饰的变量,只能在本类中使用,往往视为类的内部变量,不对外暴露。如果要访问,往往通过暴露的公共方法来访问。

    从源码学习访问控制符使用_第14张图片

    ​ 比如图中Calendar中,被private修饰的变量和常量,都只在类的内部使用。

    ​ 使用private修饰变量或方法是一种常见的封装和隐藏内部细节的方式。这样做有以下几个考虑:

    1. 封装和隐藏:private修饰符可以将变量或方法隐藏在类的内部,不允许外部类直接访问。这样可以有效地封装类的内部实现细节,避免外部类对内部实现的依赖和直接操作,提高代码的可维护性和安全性。
    2. 访问控制和安全:使用private修饰符可以限制对变量或方法的访问范围,只允许本类中的其他方法访问。这样可以更好地控制类的使用方式,避免不相关的类直接访问和操作内部状态,减少耦合性。
    3. 数据封装:private修饰符可以将变量封装在类的内部,通过公共的getter和setter方法来访问和修改变量的值。这样可以控制访问方式和对变量的操作,实现数据的封装和保护。

    ​ 需要注意的是,尽管使用private修饰符可以隐藏内部细节,但仍然可以通过反射机制来绕过访问限制。

    ​ 因此,在设计类时,除了使用private修饰符外,还需要考虑其他安全性措施,如不可变性、防御性编程和安全检查等。

你可能感兴趣的:(源码学习,数据安全,学习,java,开发语言)