cs61b week6 -- Packages and Access Control

1.Packages

在Java中,Packages是管理class和interface的命名空间(namespace),包名与网站名正好相反,比如:

ug.joshh.animal;

则对应的网站应该是:

joshh.ug

包名与文件夹路径的对应关系:
ug.joshh.animal 对应 ug/joshh/animal
使用Packages的好处是支持不同包内可以有同名的class文件,而不会混淆

1.1在Intellij IDEA中创建Packages

参考Creating a Package in IntelliJ
比较详细
简单来说,在Intellij IDEA中的操作即

File-->New-->Packages-->输入包名(ug.joshh.animal)

1.2使用Packages

如果Dog.class所在的Packages为ug.joshh.animal,则在包外使用Dog.class的话,需要声明规范名称,即

ug.joshh.animal.Dog d = new ug.joshh.animal.Dog(...);

也可以简写,前提是在文件顶部声明 import ug.joshh.animal.Dog;
就可以简写为:

Dog d = new dog();

1.3 Default Packages

任何在文件顶部没有显式包名的 Java 类都会自动被视为Default Packages的一部分。
cs61b week6 -- Packages and Access Control_第1张图片
如图所示,所有非 ug.joshh.animal 包的class文件均视为Default Packages
在实际开发中应该避免使用Default Packages,因为Default Packages不能被import,因此在Default Packages下很有可能创建相同类名的文件

1.4 .jar文件

假如你想与某人分享你的某个project的所有.class文件,可以将其打包为.jar文件,相当于.zip文件,只不过前者拥有一些额外的信息。
在Intellij IDEA中打包的方法为:

1.) Go to File → Project Structure → Artifacts → JAR → “From modules with dependencies”

2.) Click OK a couple of times

3.) Click Build → Build Artifacts (this will create a JAR file in a folder called “Artifacts”)

4.) Distribute this JAR file to other Java programmers, who can now import it into IntelliJ (or otherwise)

参考JAR Files
.jar文件并不能保障你的代码安全,因为其实质与.zip差不多,只需将其解压为.class文件,之后可以轻松将.class文件还原为.java文件


2.Access Modifiers

cs61b week6 -- Packages and Access Control_第2张图片
以上列出了不同修饰符(public protected private 与"packages private")之间的访问控制,其中黑色方块代表packages private类型,即在声明变量前不加任何修饰符,则该变量自动成为本包的私有变量,只有本包内的文件与同类可以访问,在外包的extends的子类也不能访问!

再次补充关于Defalut Packages
事实上在我们没有学习Packages之前,我们创建的文件均相当于在默认包内,没有包声明的代码自动成为默认包的一部分。
如果这些类的成员没有访问修饰符,那么成员的默认类型为packages private类型,因为所有的文件都是同一个默认包的一部分,这些成员在包内的不同class之间可以访问,这就是我们之前在未了解Packages之前为何代码能够良好运行的原因。

访问控制仅限于静态类型

上面我们说如果在同一个包内,不声明访问修饰符的变量,其默认类型是package private,但是对于 Interface 来说,如果其成员不声明访问修饰符,其默认类型是 public
除此之外,其他情况均如副标题所述 (the access depends only on the static types.)

小练习

cs61b week6 -- Packages and Access Control_第3张图片
观察上图代码,判断在Client class中的每一行是否能够正常编译,其中 BlackHole 和 CreationUtils 和 HasHair 位于同一个包universe内,而class Client位于默认包内。

主要分析编译错误的两行代码

1. b.get(0);

b的静态类型是 BlackHole ,编译时编译器检查 BlackHole 是否有 get() 方法--没有,编译错误

2. HasHair hb = (HasHair) b;

按道理来说,当我们使用强制类型转换之后,编译器会忽视b原本的类型,而直接通过编译,但是在此处,由于 HasHair 是位于 package universe内的,且整个class未声明访问修饰符,因此 HasHair class 实际上是 package private 类型,因此在默认包中无法访问,因为默认包对于 universe包来说相当于外包了。
cs61b week6 -- Packages and Access Control_第4张图片

你可能感兴趣的