java的包概念

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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值