Java 核心技术读书笔记——Java package,import和classpath
1 package和import
1.1 package
-
所有的Java
类都放置在同一个目录下,因此类之间的相互调用无显式声明调用。
- 同一个目录下,两个类的名字不能相同
- 文件过多,查找和修改都不易,且容易出错
-
Java
支持多个目录放置Java
,并且通过package/import/classpath/jar
等机制配合使用,可以支持跨目录放置和特别调用Java
类。
-
package
包,类似于C++
中的namespace
-
在Java
类文件的第一句话给出包的名称
1
2
3
4
|
package cn.edu.zzu;
public class PackageExample{
}
|
-
引用类的时候,必须采用全称引用;程序正文可以用短名称
-
PackageExample.java
必须严格放置在cn/edu/zzu
目录下
-
包名尽量唯一,常用域名逆序
1.2 import
- 在
PackageExampleTest.java
中,使用import
关键字来引入PackageExample
类
- 也可以采用
import cn.edu.zzu.*;
,*
代表这个目录下所有文件,但不包括子文件夹和子文件夹内的文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
// cn/edu/zzu/PackageExampleTest.java
package cn.edu.zzu;
public class PackageExample {
}
// cn/edu/zzu/PackageExampleTest.java
package cn.edu.zzu;
import cn.edu.zzu.PackageExample;
//如果PackageExample和当前类在同一个目录,可以省略上句import
public class PackageExampleTest {
public static void main(String[] args) {
PackageExample obj = new PackageExample();
//此处可以用类的短名称来引用
}
}
|
import
规则
import
必须全部放在package之后,类定义之前。
- 多个import的顺序无关
- 可以用
*
来引入一个目录下的所有类,比如import java.lang.*;
,此意思是引入java.lang
下面所有的类文件,但不包括java.lang
下面所有的子目录文件,即并不包括java.lang.reflect.*;
import
尽量精确,不推荐使用*
,以免新增的同名程序会使得老程序报错,面临着调用类指代不清的风险
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
|
// a/Main.java
package a;
public class Man {
}
// b/Main.java
package b;
public class Man {
}
// c/Main.java
package c;
import a.Man;
public class Test {
public static void main(String[] args) {
Man m = new Man();
b.Man m2 = new b.Man();
}
}
|
2 jar文件
jar
文件,一种扩展名为jar
的文件,是Java
所特有的一种文件格式,用于可执行文件的传播。
jar
文件实际上是一组class
文件的压缩包
- 项目中引入一个
jar
文件,就可以使用jar文件中所有类(.class
文件),无需类的源码(.java
文件)。
2.1 jar文件优势
jar
文件可以包括多个class
,比多层目录更加中、简洁实用
jar
文件经过压缩,只有一个文件,在网络下载和传播方面,更具有优势
jar
文件只包括class
,没有包含java文件,在保护源码文件知识版权方面,能够起到更好的作用
- 将多个
class
文件压缩成jar
文件,可以规定给一个版本号,更容易进行版本控制
2.2 命令行
- 手动在c:\temp创建cn.com.test.Man.java
2.2.1 编译
1
|
javac c:\temp\cn\com\test\Man.java
|
2.2.2 运行
java -classpath .;c:\temp cn.com.test.Man
1
|
java -cp .;c:temp cn.com.test.Man
|
- 第一部分:
java
,执行命令,是java.exe
的简写。
- 第二部分:
-classpath
固定格式参数,可以简写成-cp
- 第三部分: 是一个(Windows分号,Linux/Mac冒号连接起来的)字符串。按分隔符隔开,得到一个个子路径。
- 第四部分:主执行类的全称(含包名)
2.2.3 编译和运行规则
- 编译一个类,需要
java
文件的全路径,包括扩展名。
- 运行一个类,需写类名全称(非文件路径),无须写扩展名。
- 编译类的时候,需要给出这个类的所有依赖(包括依赖的类再次依赖的所有其他类)所在路径。
- 运行类的时候,需要给出这个类,以及被依赖类的路径总和。
classpath
参数也可以包含jar
包。如果路径内有空格,请将classpath
参数整体加双引号。
classpath
写在前面优先级更高。
1
|
java -classpath ".;c:\test.jar;c:\temp;c:\a bc" cn.com.test.Man
|
Java
运行时会将classpath
按照分隔符裁开,在每个子路径下一次寻找所需要的类。如果子路径是jar
文件,那就将jar
临时解压,在里面寻找。
3 Java访问权限
3.1 四种访问权限
private
:私有的,只能本类访问
default
:(通常忽略不写):同一个包内访问
protected
:同一个包,子类均可访问
public
:公开的,所有类都可以访问
|
同一个类 |
同一个包 |
不同包的子类 |
不同包的非子类 |
private |
√ |
|
|
|
default |
√ |
√ |
|
|
protected |
√ |
√ |
√ |
|
public |
√ |
√ |
√ |
√ |
3.2 使用范围
- 四种都可以用来修饰成员变量、成员方法、构造函数
default
和 public
可以修饰类
- 建议成员变量都是
private
- 建议成员方法都是
public
3.3 实例
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
/* test1/A.java */
package test1;
public class A {
private int v1 = 1;
int v2 = 2;
protected int v3 = 3;
public int v4 = 4;
private void showV1()
{
System.out.println(v1);
}
void showV2()
{
System.out.println(v2);
}
protected void showV3()
{
System.out.println(v3);
}
public void showV4()
{
System.out.println(v4);
}
}
/* test1/B.java */
package test1;
//B and A are in the same package
public class B {
public void show()
{
//B is not subclass of A
// System.out.println(v1); //error
// System.out.println(v2); //error
// System.out.println(v3); //error
// System.out.println(v4); //error
// showV1(); //error
// showV2(); //error
// showV3(); //error
// showV4(); //error
A obj = new A();
//System.out.println(obj.v1); error, private
System.out.println(obj.v2);
System.out.println(obj.v3);
System.out.println(obj.v4);
//obj.showV1(); error, private
obj.showV2();
obj.showV3();
obj.showV4();
}
}
/* test1/C.java */
package test1;
//C is a subclass of A, and in the same package of A.
public class C extends A {
public void show()
{
//System.out.println(v1); error, private
System.out.println(v2);
System.out.println(v3);
System.out.println(v4);
//showV1(); error, private
showV2();
showV3();
showV4();
A obj = new A();
//System.out.println(obj.v1); error, private
System.out.println(obj.v2);
System.out.println(obj.v3);
System.out.println(obj.v4);
//obj.showV1(); error, private
obj.showV2();
obj.showV3();
obj.showV4();
}
}
/* test2/D.java */
package test2;
import test1.A;
public class D extends A{
public void show()
{
//System.out.println(v1); error, private
//System.out.println(v2); error, default
System.out.println(v3);
System.out.println(v4);
//showV1(); error, private
//showV2(); error, default
showV3();
showV4();
A obj = new A();
//System.out.println(obj.v1); error, private
//System.out.println(obj.v2); error, default
//System.out.println(obj.v3); error, protected 只能作为子类才能访问
System.out.println(obj.v4);
//obj.showV1(); error, private
//obj.showV2(); error, default
//obj.showV3(); error protected 只能作为子类才能访问
obj.showV4();
}
}
/* test2/E.java */
package test2;
import test1.A;
public class E {
public void show()
{
//E is not a subclass of A. And E is not in the same package of A.
//System.out.println(v1); error, private
//System.out.println(v2); error, default
//System.out.println(v3);
//System.out.println(v4);
//showV1(); error, private
//showV2(); error, default
//showV3();
//showV4();
A obj = new A();
//System.out.println(obj.v1); error, private
//System.out.println(obj.v2); error, default
//System.out.println(obj.v3); error, protected 只能作为子类才能访问
System.out.println(obj.v4);
//obj.showV1(); error, private
//obj.showV2(); error, default
//obj.showV3(); error protected 只能作为子类才能访问
obj.showV4();
}
}
|