访问控制(1)
- 访问控制和代码重构有关。
- 需要考虑一条设计原则:
将不变的东西和变的东西分开来 - 类库使用者依赖类库,在类库发生变化的时候不需要对代码进行更改。通过某些约定可以实现这个准则:
- 类库编程人员必须保证不移除现有方法。
- 类库编程人员遇到的问题:不知道哪些字段或方法被客户端程序员所使用,导致对类库的修改束手束脚。
- 问题的解决方案:Java访问修饰符
- 访问修饰符的访问级别,由高到低:
- public
- protected
- package access
- private
- 作为类库设计人员,最终会尽可能将类的成员私有,只暴露希望客户端程序员操作的方法。
- 仅拥有类库组件和对类库组件访问控制的概念是不够的,还需要知道类库组件是如何组装成在一个类库单元中。这一切都由package关键词进行把控。访问修饰符的效果亦是受到类在同一个包还是单独的包的影响。
访问控制(2)
- 包里面的的类都组织在同一个命名空间下。
- 使用类的方式:
- 类的全名。
- import。
- 为了引入所有的类,使用*。
代码示例:
import java.util.*;
- 导入提供了命名空间管理的机制。
- 每个.java文件都仅有一个和文件同名的public类。文件中的其他类都是支撑类。不可以在包以外进行访问。
- java文件编译后,会输出class文件,java文件中每个类对应一个class文件。
- java将class文件压缩打包成JAR文件。java解释器负责查找、加载和解释class文件。
- 为了说明每个组件属于一个整体,需要使用package。
- package表达式必然出现在java文件首个非注释行。
代码示例:
package access;
- 包名的使用规范是全小写。
- package和import的用处是保证了类命名空间的唯一性。
- 由于java的包是由一系列class文件组成的,为了避免文件过多造成的杂乱,java采用了系统的文件分层机制。
- 包名通过class文件的路径名编码得到。
- 约定包名的第一部分为反向域名。第二个部分为class文件所在的路径名。
- java解释器工作原理:
- 查找环境变量CLASSPATH
- 基于CLASSPATH的条目、包名和类名,查找类文件
- 如果同时include了两个库且库中使用了相同的名称的类。为了避免潜在的冲突,需要使用全量类名。
- java没有了条件编译。但是通过import不同的包,可以实现不同条件下的编译。
访问控制(3)
- 包访问:没有访问修饰符的类成员。表示可以被同一包内其他的类访问。包以外的不可访问。
- 包访问将同一个包内相关类组织在一起,并相互作用。
- 允许对类成员进行访问的方式:
- 用public修饰成员
- 使成员可以包访问,并将访问类放在同一包内
- 如果是继承类,则可以访问protected成员和public成员。但是不能访问包访问权限成员。
- 使用get/set方法
- public:接口访问权限
- 默认包访问:不指定具体包的文件,编译后在同一包内,可以认为是默认包访问
- private访问:类成员不能被除本类以外的其他类访问。
- 任何认为是类的“助手”方法都可以指定为private。
- 除非必须暴露底层设计,否则所有成员变量都应该设置为private。
- protected:继承访问
- 基类中有些成员,允许继承类访问,但不允许全局访问,而且protected具有包访问权限。同一包中的其他类可访问。
访问控制(4)
- 访问控制和实现隐藏相关,将数据、方法包装在类里以及实现的隐藏被称为封装。
- 使用访问控制的理由:
- 设定客户端程序员可用的和不可用的代码。
- 将接口和实现分离
- 可以采用的类创建风格:将public成员放在开始,后面跟着protected成员,包访问成员和private成员。
访问控制(5)
- 访问修饰符也可以用来决定库中的哪个类可以被访问。
- 访问控制符出现在class关键词之前
- 类访问的限制:
- 一个文件中只能有一个public修饰的类。
- public修饰的类的名称必须准确和文件名相匹配。
- 有可能文件中没有public修饰的类。此时可以任意给文件命名
- 如果想使用包中的某个类,并且不希望对这个类的任意修改影响客户端程序,那么就移除类的public访问权限。
- 包访问权限的类成员字段还是尽可能设置为private。但是方法可以设置为与类访问权限一致,如果强制要求public,可以设置为public。
- 类不可以设置为private或者protected(内部类除外)
- 如果不希望类可以被其他使用者访问,可以将构造器设置为private,然后在类内部的静态方法中创建对象。
代码示例:
package access;
/**
* @author vincient
* @create 2020-02-08 11:12 AM
*/
public class Lunch {
void testPrivate() {
// 不可用!
// Soup1 soup = new Soup1();
}
void testStatic() {
Soup1 soup = Soup1.makeSoup();
}
void testSingleton() {
Soup2.access().f();
}
}
class Soup1 {
private Soup1() {
}
public static Soup1 makeSoup() {
return new Soup1();
}
}
class Soup2 {
private Soup2() {
}
private static Soup2 ps1 = new Soup2();
public static Soup2 access() {
return ps1;
}
public void f() {
}
}
来源:CSDN
作者:vincient爱游戏
链接:https://blog.csdn.net/weixin_42908976/article/details/104220848