手记

Java中更规范的包概念

包(package)是Java提供的一种区别类的名字空间的机制,是类的组织方式,是一组相关类和接口的集合,它提供了访问权限和命名的管理机制。Java中提供的包主要有以下3种用途。包的概念 包(package)是Java提供的一种区别类的名字空间的机制,是类的组织方式,是一组相关类和接口的集合,它提供了访问权限和命名的管理机制。Java中提供的包主要有以下3种用途。 将功能相近的类放在同一个包中,可以方便查找与使用。 由于在不同包中可以存在同名类,所以使用包在一定程度上可以避免命名冲突。 在Java中,某次访问权限是以包为单位的。 创建包 创建包可以通过在类或接口的源文件中使用package语句实现,package语句的语法格式如下: package 包名; 包名:必选,用于指定包的名称,包的名称为合法的Java标识符。当包中还有包时,可以使用“包1.包2.…….包n”进行指定,其中,包1为最外层的包,而包n则为最内层的包。 package语句通常位于类或接口源文件的第一行。例如,定义一个类Circ,将其放入com.wgh包中的代码如下: package com.wgh; public class Circ { final float PI=3.14159f; //定义一个用于表示圆周率的常量PI //定义一个绘图的方法 public void draw(){ System.out.println("画一个圆形!"); } } 说明: 在Java中提供的包,相当于系统中的文件夹。例如,上面代码中的Circ类如果保存到C盘根目录下,那么它的实际路径应该为C:/com/wgh/Circ.java。 使用包中的类 类可以访问其所在包中的所有类,还可以使用其他包中的所有public类。访问其他包中的public类可以有以下两种方法。 1.使用长名引用包中的类 使用长名引用包中的类比较简单,只需要在每个类名前面加上完整的包名即可。例如,创建Circ类(保存在com.wgh包中)的对象并实例化该对象的代码如下: com.wgh.Circ circ=new com.wgh.Circ(); 2.使用import语句引入包中的类 由于采用使用长名引用包中的类的方法比较繁琐,所以Java提供了import语句来引入包中的类。import语句的基本语法格式如下: import 包名1[.包名2.……].类名; 当存在多个包名时,各个包名之间使用“.”分隔,同时包名与类名之间也使用“.”分隔。 :表示包中所有的类。 例如,引入com.wgh包中的Circ类的代码如下: import com.wgh.Circ; 如果com.wgh包中包含多个类,也可以使用以下语句引入该包下的全部类。 import com.wgh.*;

1,包访问权限
如果你根本没有给定任何访问权限,例如像本章前面的所有示例,将会出现什么情况呢?默认访问权限没有任何关键字,但通常是指包访问权限(package access,有时也表示成为“friendly”)。这就意味着当前的包中的其他类对那个成员有访问权限,但对于在这个包之外的所有类,这个成员却是 private。由于一个编译单元,即一个文件,只能隶属于一个单一的包,所以经由包访问权限,处于某个单一编译单元之中的所有类彼此之间都是自动可访问的。包访问权限允许你将包内所有相关的类组合起来,以使它们彼此之间可以轻松地相互作用。等你把类组织起来放进一个包内之后,也就给它们的包访问权限的成员赋予了相互访问的权限,你拥有了该包内的程序代码。“只有你拥有的程序代码才可以访问你所拥有的其他程序代码”这种想法是合理的。你应该说,包访问权限为把类群聚在一个包中的做法提供了意义和理由。在许多语言中,你在文件内组织定义的方式是任意的,但在 java 中,则要强制你以一种合理的方式对它们加以组织。另外,你可能还想要排除这样的类:它们不应该访问在当前包中所定义的类。

即是包内的类可见,但是包外的类不可见。

同个包下的代码:

package bao1;

class A {
public static int i=10;
public static void set(){
System.out.println(4);
}
public static int get(){
return i;
}
public static void abc(){
System.out.println(4);
}
protected static void come(){
System.out.println(5);
}
public static void main(String[] args){
System.out.println(new A().i);
A a = new A();
A.abc();
a.come();
System.out.println(i);
}

}

package bao1;

public class AA {
public static void main(String[] args){
A a = new A();
a.get();
a.set();
a.come();
}
}
2,public:接口访问权限
当你使用关键字 public,就意味着 public 之后紧跟着的成员声明对每个人都是可用的,尤其是使用程序库的客户端程序员更是如此。假设你定义了一个包含下面编译单元的dessert 包:
//: c05:dessert:Cookie.java
// Creates a library.
package c05.dessert;
public class Cookie {
public Cookie() {
System.out.println("Cookie constructor");
}
void bite() { System.out.println("bite"); }
} ///:~
记住,
Cookie.java 产生的类文件必须位于名为 dessert 的子目录之中,该子目录在 c05之下,而 c05 则必须位于 CLASSPATH 指定的众多路径的其中之一的底下。不要错误地认为 java 总是将当前目录视作是查找行为的起点之一。如果你CLASSPATH 之中缺少一个‘.’作为路径之一的话,java 就不会查找那里。现在如果你创建了一个使用 Cookie 的程序:
//: c05:Dinner.java
// Uses the library.
import com.bruceeckel.simpletest.;
import c05.dessert.
;
public class Dinner {
static Test monitor = new Test();
public Dinner() {
System.out.println("Dinner constructor");
}
public static void main(String[] args) {
Cookie x = new Cookie();
//! x.bite(); // Can't access
monitor.expect(new String[] {
"Cookie constructor"
});
}
} ///:~
你就可以创建一个 Cookie 对象,因为 Cookie 的构造器是 public 而其自身也是 public的。(此后我们将会对 public 类的概念了解更多。)但是,由于bite( )只向在 dessert包中的类提供访问权,所以 bite( ) 成员在 Dinner.java 之中是无法访问的,为此编译器也禁止你使用它。

如果没有声明public,则只能在自己的包内使用。

3,缺省包(default package)
你会惊异地发现下面的程序代码虽然看起来是破坏了上述规则,但它仍可以进行编译。
//: c05:Cake.java
// Accesses a class in a separate compilation unit.
import com.bruceeckel.simpletest.;
class Cake {
static Test monitor = new Test();
public static void main(String[] args) {
Pie x = new Pie();
x.f();
monitor.expect(new String[] {
"Pie.f()"
});
}
} ///:~
在第二个处于相同目录的文件中:
//: c05:Pie.java
// The other class.
class Pie {
void f() { System.out.println("Pie.f()"); }
} ///:~
最初你或许会认为这两个文件毫不相关, Cake 却可以创建一个 Pie 对象并调用它的 f( )方法!(记住,为了使文件可以被编译,在你的 CLASSPATH 之中一定要有‘.’。)你通常会认为 Pie 和 f( )享有包访问权限,因而是不可以为 Cake 所用的。它们的确享有包访问权限,但这只是部分正确的。Cake.java 可以访问它们的原因是因为它们同处于一个相同的目录并且没有给自己设定任何包名称。Java 将这样的文件自动看作是隶属于该目录的缺省包之中,于是它们为该目录中所有其他的文件都提供了包访问权限。
4,Protected:继承访问权要理解 protected 的访问权限,我们在内容上需要作一点跳跃。首先,你要知道在本书介绍继承(第 6 章)之前,你并不用真正理解本节的内容。但为了内容的完整性,这里还是提供了一个使用 protected 的简要介绍和示例。关键字 protected 处理的是一个被称为继承(inheritance)的概念,借助此项技术,我们可以获取一个现有类——我们将其作为基类引用,然后将新成员添加该现有类中,而不必触及这个现有类。你还可以改变该类的现有成员的行为。为了从现有类中继承,你要声明你的新类 extends(扩展)了一个现有类,就象这样:
class Foo extends Bar {
至于类定义中的其他部分看起来都是一样的。
如果你创建了一个新包,
并继承自另一个包中的某个类,
那么你唯一可以访问的成员就是源
包的 public 成员。(当然,如果你在同一个包内执行继承工作,你就可以操纵所有的拥有
包访问权限的成员)。有时,基类的创建者会希望获得一个特定的成员,并赋予派生类,而
不是所有类以访问权。这就需要 protected 来完成这一工作。protected 也提供包访问
权限,也就是说,相同包内的其他类可以访问 protected 元素。
如果你回顾一下先前的例子 Cookie.java,
就可以得知下面的类是不可以调用拥有包访问
权限的成员 bite( )的::
//: c05:ChocolateChip.java
// Can't use package-access member from another package.
import com.bruceeckel.simpletest.
;
3
此例还有另一个效果:既然缺省构造器是唯一定义的构造器,并且它是private的,那么它将阻碍对此
类的继承。(在第 6 章我们将介绍这个问题。)
import c05.dessert.*;
public class ChocolateChip extends Cookie {
private static Test monitor = new Test();
public ChocolateChip() {
System.out.println("ChocolateChip constructor");
}
public static void main(String[] args) {
ChocolateChip x = new ChocolateChip();
//! x.bite(); // Can't access bite
monitor.expect(new String[] {
"Cookie constructor",
"ChocolateChip constructor"
});
}
} ///:~
有关于继承技术的一个很有趣的事情是如果类 Cookie 之中存在一个方法 bite( )的话,那么该方法同时也存在于任何一个从 Cookie 继承而来的类之中。但是由于 bite( )有包访问权限而且它位于另一个包内,所以我们在这个包内是无法使用它的。当然,你也可以把它指定为 public,但是这样做所有的人就都有了访问权限,而且很可能这并不是你所希望的。如果我们将类 Cookie 象这样加以更改:
public class Cookie {
public Cookie() {
System.out.println("Cookie constructor");
}
protected void bite() {
System.out.println("bite");
}
}
那么,bite( )在包 dessert 之中仍旧拥有包访问权限,但是它对于所有继承自 Cookie的类而言,也是可以使用的。然而,它不是 public 的。

0人推荐
随时随地看视频
慕课网APP