一、Java的包机制
1.1、包机制的基本概念
包机制是一个代码组织方案,用来解决名称冲突问题。为使得包的命名是独一无二的,常用的一个命名方案是使用反顺序的域名作为顶级包名。包的命名层次与目录层次结构一一对应。
1.2、包机制关键词
包机制有两个关键词:package
和import
。
1.2.1、package
package
关键词用来定义包名:package语句必须是Java源文件中除注释以外的第一个程序语句;没有package语句,表示使用默认包。
示例代码如下:
1.2.2、import
import
关键词用于导入包下的某个类(一般形式)或者全部类(通配符形式),包下某个类的静态字段和静态方法(静态导入形式);不用import
关键词就得使用类,静态字段和静态方法的全名称方式,比如java.util.List
。
在Java编程思想#一切都是对象中已经指出,所有Java源文件默认包含import java.lang.*
语句。
示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| package com.dslztx;
import java.util.ArrayList;
import java.io.*;
import static java.util.Calendar.*;
public class Main { public static void main(String[] args) { ArrayList<String> list;
File file;
System.out.println(YEAR);
java.util.Vector vector; } }
|
二、Java的访问权限控制
在本文中,“类成员”包括“一般字段,静态字段,一般方法,静态方法”。
接下来的论述内容更多的是属于“自我理解”性质的,基于“Java编译程序实现角度”推导而来。
2.1、类的实际定义
参考Java类实际定义
2.2、访问权限修饰符
访问权限修饰符有:public
,protected
,default
(包访问权限修饰符,该修饰符实质上不存在),private
。
2.2.1、类访问权限修饰符
类(本文所指“类”包含“类,抽象类,接口,枚举,注解”,不包含“内部类”)的访问权限修饰符有:public
和default
;“内部类”的访问权限修饰符有:public
,protected
,default
,private
。
2.2.2、类成员访问权限修饰符
类成员的访问权限修饰符有:public
,protected
,default
,private
。
2.3、Java资源地址和访问者地址
地址的形式是:包名:类名
。
2.3.1、Java资源地址
Java资源包括:类,类成员。Java资源地址即“Java资源定义所在地址”。
示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| package chapter6;
public class JavaResourceAddress extends JavaResourceAddressParent {
static int b;
int a;
static void g() { }
void f() { }
}
class JavaResourceAddressParent {
int c;
void h() {
} }
|
2.3.2、访问者地址
访问者地址即“访问Java资源语句所在地址”。
2.4、访问控制
对Java资源(类,类成员)的访问控制分为两部分。
2.4.1、访问控制——类
有以下两点论述:
- 当访问权限修饰符为
public
时,无论“Java资源(类)地址”和“访问者地址”关系怎样,该Java资源(类)可被访问
- 当访问权限修饰符为
default
时,只有当“Java资源(类)地址”和“访问者地址”处于同一个包中,该Java资源(类)才可被访问
2.4.2、访问控制——类成员
有以下几点论述:
- 欲访问类中“类成员”,首先须能访问类,参照“2.4.1、访问控制——类”
- 欲访问的“类成员”须存在,可通过查看该类的完整定义进行确定
- 欲访问的“类成员”是原生定义的,则参照“规则集1”;否则,即欲访问的“类成员”是隐式复制下来的,则参照“规则集2”
规则集1:
- 当访问权限修饰符为
public
时,无论“Java资源(类成员)地址”和“访问者地址”关系怎样,该Java资源(类成员)可被访问
- 当访问权限修饰符为
protected
时,只有当“Java资源(类成员)地址”和“访问者地址”处于同一个包中,该Java资源(类成员)才可被访问。在“访问控制”范畴内,protected
和default
访问权限修饰符语义完全一致
- 当访问权限修饰符为
default
时,只有当“Java资源(类成员)地址”和“访问者地址”处于同一个包中,该Java资源(类成员)才可被访问
- 当访问权限修饰符为
private
时,只有当“Java资源(类成员)地址”和“访问者地址”一致,该Java资源(类成员)才可被访问
规则集2:
- 从欲访问“复制类成员”对应节点开始可得到一条引用链
- 从前往后依次比较“访问者地址”与引用链中前
N-1
个节点对应的地址,一旦一致,则可访问;否则,再根据“规则集1”,比较“访问者地址”与引用链中最后一个节点对应的地址,满足则可访问,不满足则不可访问
2.5、继承控制
“继承控制”与“访问控制”几乎一致,即“可访问的可继承,不可访问的不可继承”,除了:子类可继承祖先类中被protected
访问权限修饰符修饰的Java资源(类成员),而与子类中是否可访问祖先类中该Java资源(类成员)无关。
综合“2.4、访问控制”和“2.5、继承控制”可知,protected
访问权限修饰符的设计意图在于“继承控制”,而不在于“访问控制”。
示例代码如下:
1 2 3 4 5 6 7 8 9
| package chapter6.subpackage1;
public class A {
protected int c;
int a;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| package chapter6.subpackage2;
import chapter6.subpackage1.A;
public class B extends A {
public void f() {
System.out.println(c); }
}
|
2.6、综合例子
2.6.1、说明
接下来的例子完整地验证了上述介绍。在该例子中,有3个包:package1,package2和package3。在3个包中包含的类说明如表1。
表1
包名 |
所包含类类名 |
package1 |
A,AA1,B |
package2 |
AA2,C |
package3 |
AAA,D |
这些类之间的关系如图1所示。
图1
2.6.2、具体代码
1、package1
类A:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| package package1;
import package2.AA2; import package3.AAA;
public class A {
public int d;
protected int c;
int b;
private int a;
public static void main(String[] args) { A a = new A(); System.out.println(a.a); System.out.println(a.b); System.out.println(a.c); System.out.println(a.d);
AA1 aa1 = new AA1(); System.out.println(aa1.b); System.out.println(aa1.c); System.out.println(aa1.d);
AA2 aa2 = new AA2(); System.out.println(aa2.c); System.out.println(aa2.d);
AAA aaa = new AAA(); System.out.println(aaa.c); System.out.println(aaa.d); }
}
|
类AA1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| package package1;
import package2.AA2; import package3.AAA;
public class AA1 extends A {
public static void main(String[] args) { A a = new A(); System.out.println(a.b); System.out.println(a.c); System.out.println(a.d);
AA1 aa1 = new AA1(); System.out.println(aa1.b); System.out.println(aa1.c); System.out.println(aa1.d);
AA2 aa2 = new AA2(); System.out.println(aa2.c); System.out.println(aa2.d);
AAA aaa = new AAA(); System.out.println(aaa.c); System.out.println(aaa.d); }
}
|
类B:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| package package1;
import package2.AA2; import package3.AAA;
public class B {
public static void main(String[] args) { A a = new A(); System.out.println(a.b); System.out.println(a.c); System.out.println(a.d);
AA1 aa1 = new AA1(); System.out.println(aa1.b); System.out.println(aa1.c); System.out.println(aa1.d);
AA2 aa2 = new AA2(); System.out.println(aa2.c); System.out.println(aa2.d);
AAA aaa = new AAA(); System.out.println(aaa.c); System.out.println(aaa.d); } }
|
2、package2
类AA2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| package package2;
import package1.A; import package1.AA1; import package3.AAA;
public class AA2 extends A {
public static void main(String[] args) { A a = new A(); System.out.println(a.d);
AA1 aa1 = new AA1(); System.out.println(aa1.d);
AA2 aa2 = new AA2(); System.out.println(aa2.c); System.out.println(aa2.d);
AAA aaa = new AAA(); System.out.println(aaa.c); System.out.println(aaa.d); } }
|
类C:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| package package2;
import package1.A; import package1.AA1; import package3.AAA;
public class C {
public static void main(String[] args) { A a = new A(); System.out.println(a.d);
AA1 aa1 = new AA1(); System.out.println(aa1.d);
AA2 aa2 = new AA2(); System.out.println(aa2.d);
AAA aaa = new AAA(); System.out.println(aaa.d); } }
|
3、package3
类AAA:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| package package3;
import package1.A; import package1.AA1; import package2.AA2;
public class AAA extends AA2 {
public static void main(String[] args) { A a = new A(); System.out.println(a.d);
AA1 aa1 = new AA1(); System.out.println(aa1.d);
AA2 aa2 = new AA2(); System.out.println(aa2.d);
AAA aaa = new AAA(); System.out.println(aaa.c); System.out.println(aaa.d); } }
|
类D:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| package package3;
import package1.A; import package1.AA1; import package2.AA2;
public class D {
public static void main(String[] args) { A a = new A(); System.out.println(a.d);
AA1 aa1 = new AA1(); System.out.println(aa1.d);
AA2 aa2 = new AA2(); System.out.println(aa2.d);
AAA aaa = new AAA(); System.out.println(aaa.d); } }
|
参考文献:
[1]http://stackoverflow.com/questions/15939002/protected-access-modifier-in-java
[2]http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html