Thinking In Java笔记(第六章 访问权限控制)

第六章 访问权限控制

简介

    Java提供了访问权限修饰词,供类库开发人员向客户端程序员指明哪些是可用的,哪些是不可用的。访问权限控制的等级,从最大权限到最小权限一次为:publicprotected、包(library)访问权限(没有关键词)以及private

6.1 包(library):库单元

    包内含有一组类,它们在单一的名字控件之下被组织在一起。例如,在Java的标准发布中有一个工具库,它被组织在java.util名字空间之下。java。util中有一个叫ArrayList的类,使用ArrayList的一种方式是用其全名java.util.ArrayList来指定。例如:

public class Test {
    public static void main(String[] args) {
        java.util.ArrayList list = new java.util.ArrayList();
    }
}

    有没有觉得很长很麻烦,可以用import关键字来导入该类,例如:

import java.util.ArrayList
public class Test {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
    }
}

    我们需要通过导入来给类一个名字空间。如果同时有两个名字为Stack类并且在同一机器上面了,这时候需要对名称空间进行完全控制,给每个类贴上唯一的标签。

    当编写一个Java源代码文件的时候,此文件通常被成为编译单元,每个编译单元都必须由一个后缀名.java,在编译单元的内部可以有一个由关键词public修饰的类,该类的名称必须和文件名相同,否则编译器报错。如果在编译单元里面有额外的类,这些类不是public的,在包之外无法被看见。

6.1.1 代码组织

    当编译一个.java文件时,在文件中的每个类都会有一个输出文件,输出的文件名和类名称相同,后缀名为.class。因此在编译少量.java文件之后,可能会的到很多.class文件,如果用编译性语言(例如C),编译之后产生的中间文件(通常是一个obj文件),然后再通过链接器(用来创建一个可执行文件)或类库产生器(librarian,用来创建一个类库)产生的其他同类文件绑定一起。

    但这不是Java的工作方式,Java可运行程序是一组可以打包并且压缩为一个Java文档文件(JAR,使用Java的jar文档生成器)的.class文件。Java解释器负责这些文件的查找、装载和解释。

    类库实际上是一组类文件。其中每个文件都有一个public类,以及人以数量的非public类。如果希望.java文件从属于同一个群组,就可以用到package关键字。

    package语句必须是一个编译单元中(.java文件)除了注释之外的第一行程序代码。例如package access;。就表明该类是名为access的类库的一部分。例如

package access.mypackage;
public class MyClass {
    .....
}

    定义好了类MyClass并且为其指定好了包名之后,如果需要用到该类,就需要用关键字import来导入类。

import access.mypackage.*;
public class Test {
    public static void main(String[] args) {
        MyClass class = new MyClass();
    }
}

6.1.2 创建独一无二的包名

    为了避免多个包的文件在同一个目录下混杂,一中合乎逻辑的做法就是将特定的包的所有.class文件都放置于一个目录下。利用操作系统的层次化的文件结构来解决这一问题。

    将所有的文件收入一个子目录还可以解决另外的两个问题:

  1. 按照惯例,package名称的第一部分是类的创建者的反顺序Internet域名,如果按照管理来命名,package的名称也将是独一无二的,防止了名称冲突的问题。
  2. 将package名称分解成本机上的一个目录。当Java程序运行并加载需要的.class文件时,就可以很直观的确定出文件所在的目录。

    Java解释器的运行过程如下:找出环境变量CLASSPATH(可以通过操作系统来设置),CLASSPATH包含了一个或者多个目录,用作查找.class文件的根目录。从根目录开始,解释器获取包的名称并将每个句点替换成反斜杠,以从CLASSPATH根中产生一个路径名称(例如包名foo.bar.baz就会变成foo\bar\baz或者foo/bar/baz,取决于操作系统)。得到的路径会和CLASSPATH中相对应的目录结合,解释器就在这些目录中查找和需要创建的类名相同的.class文件了。

6.1.3 对使用包的告示

    无论何时创建包,都已经在给定包名称的时候隐含的指定了目录结构。这个包必须位于其命名所指定的目录之中,而该目录必须是在CLASSPATH开始的目录中可以查询到的。注意,编译过的代码通常放置在和源代码不同的目录中,但必须保证JVN使用CLASSPATH能找到该路径

6.2 Java访问权限关键词

    public、protected、private这几个Java访问权限修饰词在使用的时候,是放在类中每个成员的定义之前,无论这个成员是一个方法还是变量。如果不提供任何形式访问权限修饰,则意味着它是”包(package)访问权限”。

6.2.1 包(package)访问权限

    类中的默认访问权限没有任何的关键字,但通常指的是包访问权限(有时也表示称friendly)。这就意味着当前包中的所有其他类对该成员都有访问的权限,但对这个包之外的所有类,却表现出private的特性。

    包访问权限允许将包内所有相关的类组合起来,以使它们可以轻松的相互作用。当把类组织起来放进一个包内时,也就给他们的报访问权限的成员赋予了相互访问的权限。

6.2.2 public:接口访问权限

    使用关键字public,也就意味着后面紧跟着的成员无论对谁都可直接访问,假设定义了一个包含下面编译单元的dessert包:

package access.dessert;
public class Cookie {
    public Cookie() {
        System.out.println("Cookie constructor");
    }
    void bite() {
        System.out.println("bite");
    }
}

    现在如果创建了一个使用Cookie类的程序:

import access.dessert.*;
public class Dinner {
    public static void main(String[] args) {
        Cookie x = new Cookie();
    }
}

    这样就可以创建一个Cookie对象了,但是由于bite方法是包内访问权限,不在一个包内,故无法访问该方法。

默认包:如果对两个类都没有用package关键字指明所处的包,则会默认该文件你属于该目录的默认包中,如果这两个类在同一个子目录下,则是可以互相访问包访问权限的成员的。如果上面的例子中两个类文件处于同一目录下,则可以调用x.bite()方法,否则会报错。

6.2.3 private:无法访问

    关键字private的意思是,除了包含该成员的类之外,其他任何类都无法访问这个成员。下面的例子使用了private关键字:

class Sundae{
    private Sudae() {
        static Sudae makeASudae(){
        return new Sudae();
    }
}

public class IceCream {
    public static void main(String[] args) {
        Sundae x = Sundae.makeSundae();
    }
}

    这个例子阻止外界直接接触构造器,而用作者提供的构造器来创建类的实例。

    任何可以肯定只是该类的一个”助手”的方法,都可以指定成private,以确保不会再包内其他地方误用。

6.2.4 protected:继承访问权限

    关键字protected处理的是继承的概念,通过继承可以利用一个基类,然后将新成员添加到现有类中而不用碰该现有类。还可以改变该类现有成员的行为。

    如果创建了一个新包,并继承来自另外一个包的基类,则唯一能访问的成员就是基类中的public成员。基类的创建者会希望某个特定的成员,把它的访问权限赋予它的子类而不是所有类,这就需要用到protected关键字。protected也提供包访问权限,也就是说是加强版的默认访问权限,除了同一包里的类可以访问之外,还允许继承它的类访问。下面的例子:

//Cookie.java
package access.dessert;
public class Cookie {
    public Cookie() {
        System.out.println("Cookie constructor");
    }
    void bite() {
        System.out.println("bite");
    }
}

    目前对方法bite()有访问权限的只有同一包下的。
如果再创建一个类继承Cookie,并将bite()方法的访问权限改为protected

//SmallCookie.java
package dada.life
public class SmallCookie extends Cookie{
    public SmallCookie() {
        System.out.println("SmallCookie constructor"):
    }
    public void smallBite() {
        bite();
    }
    public static void main() {
        SmallCookie sc = new SmallCookie();
        sc.smallBite();
    }
}

    这时候SmallCookie对Cookie中的bite()方法就具有了访问权限。

6.4 类的访问权限

    Java中,访问权限修饰词也可以用于确定库中的哪些类对于使用者时可用的。

    为了控制某个类的访问权限,修饰词必须出现在关键字class之前。例如public class Widget{},然而在使用关键字限制访问权限的时候还有些注意事项:

  1. 每个编译单元(文件)都只能有一个public类。每个编译单元都有单一的公共接口,用public来修饰。
  2. public修饰的类必须和编译单元(文件)同名,包括大小写。

    请注意,类的访问权限既不可以是private(这样会使其他的任何类都无法访问它)也不能是protected的。所以对类的访问权限只有两个选择:包访问权限或者public。如果不希望其他任何人对该类拥有访问权限,可以把所有构造器都设置为private

    如果没能为类访问权限指定一个访问修饰符,它就会默认的得到包访问权限。这就意味着该类的对象可以由包内的任何其他类来创建,但是在包外则不行。(在类的最开头,由package指定的包名相同则视为同一包下,还需要注意默认包名~)。

你可能感兴趣的:(Java编程思想,java权限,访问权限,public,private,protected)