Java
中为什么要设计访问权限控制机制呢?
主要作用有两点:
(1)
为了使用户不要触碰那些他们不该触碰的部分,这些部分对于类内部的操作时必要的,但是它并不属于客户端程序员所需接口的一部分。
(2)
为了让类库设计者可用更改类的内部工作方式,而不必担心会对用户造成重大影响。
Java
中的访问权限控制的等级,按照权限从大到小依次为
:
Public -> protected ->
包访问权限(没有权限修饰词)
-> private
。
包
(package)
Java
中包
(package)
的概念和
C++
中命名空间
(namespace)
的概念很类似,都可以限制类的作用域。二者最大的差别在于,
Java
中的包隐式地指明了类的树形层级结构(同时也是
Java
源码文件的目录结构)。这样做的好处在于:可以通过文件系统中对于文件路径唯一性的要求来限制类的唯一性。
编写一个
Java
源代码文件
(
.java
文件
)
时,此文件通常被称为
编译单元
。在编译单元内最多允许有一个
public
类,且该类的名称必须与文件名完全相同(包括大小写)。
编译一个
.java
文件时,在
.java
文件中的每个类都会有一个
.class
输出文件,这个文件名和类名是相同的。
Java
可运行程序是一组可以打包并压缩为一个
Java
文档文件
(JAR
包,使用
Java
的
jar
文档生成器
)
的
.class
文件。
Java
解释器负责这些文件的查找、装载和解释。
类库实际上是一组类文件。其中每个
.java
文件最多允许有一个
public
类,以及任意数量的非
public
类。因此,每个文件都有一个构件。如果要将这些构件(每个构建有一个
.java
文件和若干个
.class
文件)组织起来,形成不同的群组,可以使用
Java
中的关键字
package
。
包
(package)
的作用
(1)
把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用。
(2)
如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。
(3)
包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。
Java
中,使用
package
关键字来指定代码所属的包(命名空间)。
语法格式:
(1)
包的名字隐含地指出了代码的目录结构。
(2)
同一目录下的
public
类名(同时也是
java
文件名)应该是独一无二的。
(3)
包声明应该在源文件的第一行,每个源文件只能有一个包声明,这个文件中的每个类型都应用于它。
(4)
如果一个源文件中没有使用包声明,那么其中的类,函数,枚举,注释等将被放在一个无名的包(
unnamed package
)中。
(5)
package
的名字一般全是小写字母。
查看
java.util.ArrayList
类的源码可以看到文件第一行代码为:
package
:包访问权限
如果不提供任何访问权限修饰词,则意味着它是
包访问权限
。
默认访问权限
没有任何关键字
,但通常是指
包访问权限
(有时也表示为
friendly
,有点像
C++
中的友元概念
)。这意味着包中所有其他类都可以访问这个成员或方法,但是
这个包之外的所有类不可以访问
。
com.notes.packages.test
.Info
package
com.notes.packages.test;
public
class
Info {
void
print() { System.
out
.println(
"default method -- print()"
); }
package
com.notes.packages.test;
public
class
PublicDemo01 {
public
static
void
main(String[]
args
) {
Info
x
=
new
Info();
x
.print();
package
com.notes.packages;
import
com.notes.packages.test.Info;
public
class
PublicDemo02 {
public
static
void
main(String[]
args
) {
Info
x
=
new
Info();
// x.print(); // Error
package
com.notes.packages.test;
public
class
Info {
public
void
print() { System.
out
.println(
"public method -- print()"
); }
protected
:继承访问权限
新类(称之子类或派生类)通过继承可以复用一个现有类(称之父类或基类),然后扩展基类的成员、方法。有时,基类的创建者会希望某个特定成员,将它的访问权限赋予派生类而不是所有类。
public
无法做到这一点,为此,引入了
protected
来完成这一工作。
protected
也提供包访问权限,也就是说,
派生类以及相同包内的其他类都可以访问
protected
成员或方法
。
例:子类继承父类后,可以访问父类的
protected
成员。
private
String
a
=
"private"
;
protected
String
b
=
"protected"
;
public
String
c
=
"public"
;
class
Son
extends
Father {
public
void
print() {
// System.out.println("element a
:
" + super.a); // Error
System.
out
.println(
"element b
:
"
+
super
.
b
);
System.
out
.println(
"element c
:
"
+
super
.
c
);
public
class
ProtectedDemo01 {
public
static
void
main(String
args
[]) {
Son
sub
=
new
Son();
sub
.print();
除此之外,还有一些需要注意的点:
(1)
静态成员、静态方法的权限修饰词的用法和普通成员、方法一样。
(2)
类虽然也可以被修饰词修饰,但是不可以用
private
、
protected
两个权限修辞词。
(3)
有些书中将包访问权限又叫做默认访问权限。个人不建议这么去记,因为这很容易与
Java Se8
中新特性
——
default
关键字混淆。这个关键字只能用于
Interface
,作用是
允许程序员在
Interface
中定义接口的默认具体实现
(以往的
JDK
版本是不允许这样的,你只能在接口中声明方法)。