《JAVA编程思想(第四版)》第六章(访问权限控制)小结
控制对成员的访问权限有两个原因.
第一,为了使用户不要碰触那些他们不该碰触的部分,这些部分对于类内部的操作时必要的,但是他并不属于客户端程序员所需接口的一部分.因此,将方法和域指定称private,对客户端程序员而言是一种服务.
第二.为了让类库设计者可以更改类的内部工作方式,而不必担心这样会对客户端程序员产生重大的影响.
tip:访问权限控制专注于类库创建者和该类库的外部使用者之间的关系,这种关系是一种通信方式
访问控制(或隐藏具体实现)与"最初的实现并不恰当"有关.换句话说就是:"我们的代码几乎不可能在一开始就做到最好,后期的迭代可以逐步改善情况,访问控制很大情况下就是为了后续代码的改善".
因为如果别的程序员可以随意调用你的代码中的任何东西.
想象一下,你正在写一个方法a(),你只想让其他人调用a()
void a(){
b();
c();
}
void b(){}
void c(){}
而有一个程序员在他认为可以的情况下调用了你的c(),
而后来你发现,c()与b()方法有更好的e()方法实现,于是你删掉了c(),改变了a();并且认为这个改动不会对调用a()的人产生影响.
void a(){
e();
}
void e(){}
此时,调用c()的代码就会遇到大麻烦了.
诸如此类的情况很多,有很多情况下,我不想让调用a()的人看到我拥有b(),c(),d(),以及一些变量,
比如Java中String的内部char[],他不希望你调用这个,你只用调用他提供好的方法就可以了,而随着算法的改进,对于客户端程序员只收到代价的降低,而不需要改进任何代码.
这就是Java提出来的访问权限:
public > protected > 包访问权限(没有关键字) > private.(公开性由高到底).
权限名称 |
public |
protected |
default |
private |
对应权限 |
无论是谁无论在哪里,都可以访问该成员 | 继承类,同一包下,可以访问到. | 只有同一包下可以访问 |
不允许其他类访问 |
包内有一组类,他们在单一的名字空间下呗组织在一起.
我们可以通过
import java.util.ArrayList;
导入在java包下的util包中的ArrayList.java文件.使这行语句所在的类可以使用其提供的方法和变量.
java.util.ArrayList aList = new java.util.ArrayList();//也是合法的.
package语句必须是文件中除注释以外的第一句程序代码.
package access; //必须是第一行程序代码
Java包的命名规则全部使用小写字母,包括中间的字也是.(曾有部分大写,现在已经全部规定为小写.)
package package.method.access; //必须全部是.
package和import关键字允许你做的,是将单一的全局名字空间分隔开,使得无论多少人使用Internet以及Java开始编写类,都不会出现名称冲突问题.
为了不出现类名,我们自己写的代码应该尽可能放在自己的包下,而为了保证不出现包名也冲突,所以使用一套独有的包命名规则:域名命名,
//假设我现在拥有域名:testpackage.com,
//那么我自己的包名为:
package com.testpackage.util;//util为我的名为util的类库,用来存放我的一些工具类.
访问权限的控制常被称为是具体实现的隐藏,把数据和方法包装在类中,以及具体实现的隐藏,常共同被称作为封装.其结果是一个同时带有特征和行为的数据类型.
- 每个编译单元都必须有一个后缀名.java
- 而在编译单元内则可以有一个public类
- 该类的名称必须与文件的名称相同(包括大小写,但不包含后缀名.java)
- 每个编译器最多只能用一个public 类,否则编译器就不会接受
- 编译单元内完全不带public类也是可能的.此时可以随意对文件命名.(可能会付出debug的代价.)
对于某个类,只有 public 和包访问权限(default),不可以是 private 和 protected.
如果不想要他人生成该类,可以把所有的构造器都置为 private权限,从而阻止任何人创建该类的对象.但是有一个例外,就是你在该类的static成员内部可以创建.
package unit06_access.util.blog;
class Soup1 {
private Soup1() {}
public static Soup1 makeSoup() {
return new Soup1();
}
}
class Soup2 {
private Soup2() {}
private static Soup2 soup2 = new Soup2();
public static Soup2 access() {
return soup2;
}
public void f() {}
}
public class Lunch {
void testPrivate() {
// Soup1 soup1 = new Soup1();//编译器提醒:The constructor Soup1() is not visible
}
void testStatic() {
Soup1 soup1 = Soup1.makeSoup(); //合法
}
void testSingleton() {
Soup2.access().f(); //单例模式,始终只有soup2一个对象.
}
}