0%

Java编程思想#访问权限控制

一、Java的包机制

1.1、包机制的基本概念

包机制是一个代码组织方案,用来解决名称冲突问题。为使得包的命名是独一无二的,常用的一个命名方案是使用反顺序的域名作为顶级包名。包的命名层次与目录层次结构一一对应。

1.2、包机制关键词

包机制有两个关键词:packageimport

1.2.1、package

package关键词用来定义包名:package语句必须是Java源文件中除注释以外的第一个程序语句;没有package语句,表示使用默认包。
示例代码如下:

1
package com.dslztx;

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类由"import java.util.ArrayList"语句导入
ArrayList<String> list;

// File类由"import java.io.*"语句导入
File file;

// 静态字段"YEAR"由"import static java.util.Calendar.*"语句导入
System.out.println(YEAR);


// 不使用"import"语句,就得使用全名称方式
java.util.Vector vector;
}
}

二、Java的访问权限控制

在本文中,“类成员”包括“一般字段,静态字段,一般方法,静态方法”。
接下来的论述内容更多的是属于“自我理解”性质的,基于“Java编译程序实现角度”推导而来。

2.1、类的实际定义

参考Java类实际定义

2.2、访问权限修饰符

访问权限修饰符有:publicprotecteddefault(包访问权限修饰符,该修饰符实质上不存在),private

2.2.1、类访问权限修饰符

类(本文所指“类”包含“类,抽象类,接口,枚举,注解”,不包含“内部类”)的访问权限修饰符有:publicdefault;“内部类”的访问权限修饰符有:publicprotecteddefaultprivate

2.2.2、类成员访问权限修饰符

类成员的访问权限修饰符有:publicprotecteddefaultprivate

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;

//“JavaResourceAddress”这个Java资源(类)的地址为“chapter6.JavaResourceAddress”
public class JavaResourceAddress extends JavaResourceAddressParent {

//“b”这个Java资源(原生类成员)的地址为“chapter6.JavaResourceAddress”
static int b;

//“a”这个Java资源(原生类成员)的地址为“chapter6.JavaResourceAddress”
int a;

//“g()”这个Java资源(原生类成员)的地址为“chapter6.JavaResourceAddress”
static void g() {
}

//“f()”这个Java资源(原生类成员)的地址为“chapter6.JavaResourceAddress”
void f() {
}

//“c”这个Java资源(复制类成员)的地址为“chapter6.JavaResourceAddress”

//“h()”这个Java资源(复制类成员)的地址为“chapter6.JavaResourceAddress”

}

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资源(类成员)才可被访问。在“访问控制”范畴内,protecteddefault访问权限修饰符语义完全一致
  • 当访问权限修饰符为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 {

//类B的完整定义
//int c;

public void f() {
//加上注释语句,编译出错
//System.out.println(a);

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;

/**
* 父类
*
* @author dsl
*/
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();
//不能访问,在该类的完整定义中,“a”类成员不存在
//System.out.println(aa1.a);
//能访问,引用链中最后一个节点对应地址与“访问者地址”满足“规则集1”
System.out.println(aa1.b);
//能访问,引用链中最后一个节点对应地址与“访问者地址”满足“规则集1”
System.out.println(aa1.c);
//能访问,引用链中最后一个节点对应地址与“访问者地址”满足“规则集1”
System.out.println(aa1.d);

AA2 aa2 = new AA2();
//不能访问,在该类的完整定义中,“a”类成员不存在
//System.out.println(aa2.a);
//不能访问,在该类的完整定义中,“b”类成员不存在
//System.out.println(aa2.b);
//能访问,引用链中最后一个节点对应地址与“访问者地址”满足“规则集1”
System.out.println(aa2.c);
//能访问,引用链中最后一个节点对应地址与“访问者地址”满足“规则集1”
System.out.println(aa2.d);

AAA aaa = new AAA();
//不能访问,在该类的完整定义中,“a”类成员不存在
//System.out.println(aaa.a);
//不能访问,在该类的完整定义中,“b”类成员不存在
//System.out.println(aaa.b);
//能访问,引用链中最后一个节点对应地址与“访问者地址”满足“规则集1”
System.out.println(aaa.c);
//能访问,引用链中最后一个节点对应地址与“访问者地址”满足“规则集1”
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;

/**
* 同包子类(注释掉的资源表示不能被访问)
*
* @author dsl
*/
public class AA1 extends A {

//类的完整定义包含下面“复制类成员”
//public int d;
//protected int c;
//int b;

public static void main(String[] args) {
A a = new A();
//不能访问,“类成员地址”与“访问者地址”不满足“规则集1”
//System.out.println(a.a);
System.out.println(a.b);
System.out.println(a.c);
System.out.println(a.d);

AA1 aa1 = new AA1();
//不能访问,在该类的完整定义中,“a”类成员不存在
//System.out.println(aa1.a);
//能访问,引用链中第一个节点对应地址与“访问者地址”一致
System.out.println(aa1.b);
//能访问,引用链中第一个节点对应地址与“访问者地址”一致
System.out.println(aa1.c);
//能访问,引用链中第一个节点对应地址与“访问者地址”一致
System.out.println(aa1.d);

AA2 aa2 = new AA2();
//不能访问,在该类的完整定义中,“a”类成员不存在
//System.out.println(aa2.a);
//不能访问,在该类的完整定义中,“b”类成员不存在
//System.out.println(aa2.b);
//能访问,引用链中最后一个节点对应地址与“访问者地址”满足“规则集1”
System.out.println(aa2.c);
//能访问,引用链中最后一个节点对应地址与“访问者地址”满足“规则集1”
System.out.println(aa2.d);

AAA aaa = new AAA();
//不能访问,在该类的完整定义中,“a”类成员不存在
//System.out.println(aaa.a);
//不能访问,在该类的完整定义中,“b”类成员不存在
//System.out.println(aaa.b);
//能访问,引用链中最后一个节点对应地址与“访问者地址”满足“规则集1”
System.out.println(aaa.c);
//能访问,引用链中最后一个节点对应地址与“访问者地址”满足“规则集1”
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;

/**
* 访问父类,子类1,子类2,孙类,跟父类和子类1同包(注释掉的资源表示不能被访问)
*
* @author dsl
*/
public class B {

public static void main(String[] args) {
A a = new A();
//不能访问,“类成员地址”与“访问者地址”不满足“规则集1”
//System.out.println(a.a);
System.out.println(a.b);
System.out.println(a.c);
System.out.println(a.d);

AA1 aa1 = new AA1();
//不能访问,在该类的完整定义中,“a”类成员不存在
//System.out.println(aa1.a);
//能访问,引用链中最后一个节点对应地址与“访问者地址”满足“规则集1”
System.out.println(aa1.b);
//能访问,引用链中最后一个节点对应地址与“访问者地址”满足“规则集1”
System.out.println(aa1.c);
//能访问,引用链中最后一个节点对应地址与“访问者地址”满足“规则集1”
System.out.println(aa1.d);

AA2 aa2 = new AA2();
//不能访问,在该类的完整定义中,“a”类成员不存在
//System.out.println(aa2.a);
//不能访问,在该类的完整定义中,“b”类成员不存在
//System.out.println(aa2.b);
//能访问,引用链中最后一个节点对应地址与“访问者地址”满足“规则集1”
System.out.println(aa2.c);
//能访问,引用链中最后一个节点对应地址与“访问者地址”满足“规则集1”
System.out.println(aa2.d);

AAA aaa = new AAA();
//不能访问,在该类的完整定义中,“a”类成员不存在
//System.out.println(aaa.a);
//不能访问,在该类的完整定义中,“b”类成员不存在
//System.out.println(aaa.b);
//能访问,引用链中最后一个节点对应地址与“访问者地址”满足“规则集1”
System.out.println(aaa.c);
//能访问,引用链中最后一个节点对应地址与“访问者地址”满足“规则集1”
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;

/**
* 不同包子类(注释掉的资源表示不能被访问)
*
* @author dsl
*/
public class AA2 extends A {

//类的完整定义包含下面“复制类成员”
//public int d;
//protected int c;

public static void main(String[] args) {
A a = new A();
//不能访问,“类成员地址”与“访问者地址”不满足“规则集1”
//System.out.println(a.a);
//不能访问,“类成员地址”与“访问者地址”不满足“规则集1”
//System.out.println(a.b);
//不能访问,“类成员地址”与“访问者地址”不满足“规则集1”
//System.out.println(a.c);
System.out.println(a.d);

AA1 aa1 = new AA1();
//不能访问,在该类的完整定义中,“a”类成员不存在
//System.out.println(aa1.a);
//不能访问,“规则集2”不满足
//System.out.println(aa1.b);
//不能访问,“规则集2”不满足
//System.out.println(aa1.c);
//能访问,引用链中最后一个节点对应地址与“访问者地址”满足“规则集1”
System.out.println(aa1.d);

AA2 aa2 = new AA2();
//不能访问,在该类的完整定义中,“a”类成员不存在
//System.out.println(aa2.a);
//不能访问,在该类的完整定义中,“b”类成员不存在
//System.out.println(aa2.b);
//能访问,引用链中第一个节点对应地址与“访问者地址”一致
System.out.println(aa2.c);
//能访问,引用链中第一个节点对应地址与“访问者地址”一致
System.out.println(aa2.d);

AAA aaa = new AAA();
//不能访问,在该类的完整定义中,“a”类成员不存在
//System.out.println(aaa.a);
//不能访问,在该类的完整定义中,“b”类成员不存在
//System.out.println(aaa.b);
//能访问,引用链中第二个节点对应地址与“访问者地址”一致
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;

/**
* 访问父类,子类1,子类2,孙类,跟子类2同包(注释掉的资源表示不能被访问)
*
* @author dsl
*/
public class C {

public static void main(String[] args) {
A a = new A();
//不能访问,“类成员地址”与“访问者地址”不满足“规则集1”
//System.out.println(a.a);
//不能访问,“类成员地址”与“访问者地址”不满足“规则集1”
//System.out.println(a.b);
//不能访问,“类成员地址”与“访问者地址”不满足“规则集1”
//System.out.println(a.c);
System.out.println(a.d);

AA1 aa1 = new AA1();
//不能访问,在该类的完整定义中,“a”类成员不存在
//System.out.println(aa1.a);
//不能访问,“规则集2”不满足
//System.out.println(aa1.b);
//不能访问,“规则集2”不满足
//System.out.println(aa1.c);
//能访问,引用链中最后一个节点对应地址与“访问者地址”满足“规则集1”
System.out.println(aa1.d);

AA2 aa2 = new AA2();
//不能访问,在该类的完整定义中,“a”类成员不存在
//System.out.println(aa2.a);
//不能访问,在该类的完整定义中,“b”类成员不存在
//System.out.println(aa2.b);
//不能访问,“规则集2”不满足
//System.out.println(aa2.c);
//能访问,引用链中最后一个节点对应地址与“访问者地址”满足“规则集1”
System.out.println(aa2.d);

AAA aaa = new AAA();
//不能访问,在该类的完整定义中,“a”类成员不存在
//System.out.println(aaa.a);
//不能访问,在该类的完整定义中,“b”类成员不存在
//System.out.println(aaa.b);
//不能访问,“规则集2”不满足
//System.out.println(aaa.c);
//能访问,引用链中最后一个节点对应地址与“访问者地址”满足“规则集1”
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;

/**
* 跨了两层包的孙类(注释掉的资源表示不能被访问)
*
* @author dsl
*/
public class AAA extends AA2 {
//类的完整定义包含下面“复制类成员”
//public int d;
//protected int c;

public static void main(String[] args) {
A a = new A();
//不能访问,“类成员地址”与“访问者地址”不满足“规则集1”
//System.out.println(a.a);
//不能访问,“类成员地址”与“访问者地址”不满足“规则集1”
//System.out.println(a.b);
//不能访问,“类成员地址”与“访问者地址”不满足“规则集1”
//System.out.println(a.c);
System.out.println(a.d);

AA1 aa1 = new AA1();
//不能访问,在该类的完整定义中,“a”类成员不存在
//System.out.println(aa1.a);
//不能访问,“规则集2”不满足
//System.out.println(aa1.b);
//不能访问,“规则集2”不满足
//System.out.println(aa1.c);
//能访问,引用链中最后一个节点对应地址与“访问者地址”满足“规则集1”
System.out.println(aa1.d);

AA2 aa2 = new AA2();
//不能访问,在该类的完整定义中,“a”类成员不存在
//System.out.println(aa2.a);
//不能访问,在该类的完整定义中,“b”类成员不存在
//System.out.println(aa2.b);
//不能访问,“规则集2”不满足
//System.out.println(aa2.c);
//能访问,引用链中最后一个节点对应地址与“访问者地址”满足“规则集1”
System.out.println(aa2.d);

AAA aaa = new AAA();
//不能访问,在该类的完整定义中,“a”类成员不存在
//System.out.println(aaa.a);
//不能访问,在该类的完整定义中,“b”类成员不存在
//System.out.println(aaa.b);
//能访问,引用链中第一个节点对应地址与“访问者地址”一致
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;

/**
* 访问父类,子类1,子类2,孙类,跟孙类同包(注释掉的资源表示不能被访问)
*
* @author dsl
*/
public class D {

public static void main(String[] args) {
A a = new A();
//不能访问,“类成员地址”与“访问者地址”不满足“规则集1”
//System.out.println(a.a);
//不能访问,“类成员地址”与“访问者地址”不满足“规则集1”
//System.out.println(a.b);
//不能访问,“类成员地址”与“访问者地址”不满足“规则集1”
//System.out.println(a.c);
System.out.println(a.d);

AA1 aa1 = new AA1();
//不能访问,在该类的完整定义中,“a”类成员不存在
//System.out.println(aa1.a);
//不能访问,“规则集2”不满足
//System.out.println(aa1.b);
//不能访问,“规则集2”不满足
//System.out.println(aa1.c);
//能访问,引用链中最后一个节点对应地址与“访问者地址”满足“规则集1”
System.out.println(aa1.d);

AA2 aa2 = new AA2();
//不能访问,在该类的完整定义中,“a”类成员不存在
//System.out.println(aa2.a);
//不能访问,在该类的完整定义中,“b”类成员不存在
//System.out.println(aa2.b);
//不能访问,“规则集2”不满足
//System.out.println(aa2.c);
//能访问,引用链中最后一个节点对应地址与“访问者地址”满足“规则集1”
System.out.println(aa2.d);

AAA aaa = new AAA();
//不能访问,在该类的完整定义中,“a”类成员不存在
//System.out.println(aaa.a);
//不能访问,在该类的完整定义中,“b”类成员不存在
//System.out.println(aaa.b);
//不能访问,“规则集2”不满足
//System.out.println(aaa.c);
//能访问,引用链中最后一个节点对应地址与“访问者地址”满足“规则集1”
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
您的支持将鼓励我继续分享!