第六章 访问权限控制
- 初学Java的时候很纳闷,为什么要提供各种访问修饰,都用public不就行了,程序都能运行,还多省事
- 我感觉如果这个程序只有你自己去编写,去维护,那么其实访问权限可以忽略
- 但是,比如说我写了一个第三方开源库,有很多很多的人在使用我的库,那么如果我对任何东西都不去限制,那么“客户端程序员”就可以去调用库中的任何东西,但是我要维护这个库,要出新版本,我根本不知道大家在用我库中的什么东西,那我怕影响大家的使用,不敢删除任何的东西,那我作为类库的开发者就无法对任何东西做出改动。所以这就是访问权限控制出现的原因
6.1 包:库单元
- A类中的方法f()和B类中的方法f()是不会冲突的
- 如何防止不同程序的同名类冲突,引入了包的概念
- 相当于电脑文件夹,我两个不同的文件夹都有一个相同名字的文件,并不冲突
6.1.1 代码组织
- Java可运行程序是一组可以打包并压缩为jar的.class文件
- 在每一个类的开头都会有package关键字,去声明你所设计的类属于谁
- import关键字会让代码更加的简洁
- 必须要牢记:package和import,使得无论多少人编写类,都不会出现名称冲突的问题
6.1.2 创建独一无二的包名
- 一般用自己的域名将顺序倒过来,可以得到一个独一无二的域名(不过也不一定),不过不大可能冲突了
练习1、略
冲突
- import java.util.*
- import new.mindview.simple.*
- 如果他们都含有Vetor,那么我们在创建一个Vetor实例的话就会发生冲突,编译器不知道取哪个Vetor
练习2、略
6.1.3 定制工具库
比如说将System.out.pringln()定制在一个工具类中,创建一个静态的方法,直接使用
也就是我们平时说的封装一些复杂的操作,然后用工具类一行代码就解决
无论什么时候我们拥有了新的工具,都可以放到自己的类库中去
6.1.4 用import改变行为
练习3、略
6.1.5 对使用包的忠告
无笔记
6.2 Java访问权限修饰词
6.2.1 包访问权限
默认访问权限,没有关键字,当前的包中的所有其他类都对那个成员有访问权限
6.2.2 public:接口访问权限
public后面紧跟着的成员声明自己对每个人都是可用的
默认包
两个文件都没有创建包,但是会认为它们有一个默认的包,使用包访问权限也可以访问
6.2.3 private:你无法访问
除了包含该成员的类之外,其他任何类都无法访问这个成员,自己隔离自己
通常要考虑的是,哪些成员是想要明确公开给客户端程序员使用的,将它们声明为public
6.2.4 protected:继承访问权限
比包访问权限多了一个子类可以访问
练习4、略
练习5、略
练习6、略
6.3 接口和实现
- 具体实现的隐藏,常被称作是“封装”
- 访问权限控制将权限划在了数据类型的内部,有两个原因,说实话,挺难理解。。。
- public成员置于开头,后面跟着protected、包访问权限、和private成员的创建类的形式
6.4 类的访问权限
每一个文件(类)只能有一个public类,比如或其他内部类就不能声明为public了
文件名必须和类名一样
练习7、略
对于类的访问权限,一般就是public和包访问权限,private和protected很少用
构造器私有化防止在其他类创建该类的对象,比如说单例模式
练习8、客户端程序员不能直接创建Connection对象,通过ConnectionManager的static方法来获取
// 这两个类在同一个包下 public class Connection { private static int counter = 0; private int id = counter++; Connection() { } public String toString() { return "Connection " + id; } public void doSomething() { } } public class ConnectionManager { private static Connection[] pool = new Connection[10]; private static int counter = 0; static { for(int i = 0; i < pool.length; i++) pool[i] = new Connection(); } // Very simple -- just hands out each one once: public static Connection getConnection() { if(counter < pool.length) return pool[counter++]; return null; } } public class E08_ConnectionManager { public static void main(String args[]) { Connection c = ConnectionManager.getConnection(); while(c != null) { System.out.println(c); c.doSomething(); c = ConnectionManager.getConnection(); } } }
练习9、运行代码,为什么编译器会出现错误
解决方案:PackagedClass位于自己的包中,不是公共类,因此在包access.local之外不可用。 如果Foreign也是access.local的一部分,那么它将与PackagedClass在同一个包中,并且可以访问它。
6.5 总结
1、当创建了一个类库,也就是与客户端程序员建立了某种关系,客户端程序员使用你的类库构建应用程序,或者更大的类库,如果不指定规则,所有事物都是公开的,不太好
2、package和import使得名称冲突的问题是很容易避免的
3、访问控制的原因有二:
- 告诉客户端程序员哪些该碰,哪些不该碰,告诉他们什么重要,什么不重要
- 让类库设计者可以随意更改它们的代码,而不必考虑会影响到使用者
4、如果你自己编写了所有的代码,所有东西都在一个包中,那么访问修饰不一定需要严格遵守