java编程思想 第六章

第六章 访问权限控制

1.访问权限控制的等级

  • 从最大权限到最小权限依次为:public、protected、包访问权限(没有关键字)和private。

2.包:库单元

Java用package关键字将构件捆绑到一个内聚的类库单元中。当编写一个Java源代码文件时,此文件通常被称为编译单元(有时也被称为转译单元)。每个编译单元必须有一个后缀名.java,而在编译单元内则可以有一个public类,该类的名称必须与文件的名称相同(包括大小写,但不包括文件的后缀名.java)。每个编译单元只能有一个public类,否则编译器就不会接受。如果在该编译单元之中还有额外的类的话,那么在包之外的世界是无法看到这些类的,这是因为它们不是public类,而且它们主要用来为主public类提供支持

  • package语句必须是文件中除注释以外的第一句程序代码。
  • Java包的命名规则全部使用小写字母,包括中间的字也是如此。

3.Java访问权限修饰词

访问权限修饰词可以类中每个成员的定义之前(无论它是一个域还是一个方法)。

包访问权限

  • 默认访问权限没有任何关键字,但是通常是指包访问权限(有时也表示成为friendly)。其意味着当前的包中所有其他类对那个成员都有访问权限,但是对于这个包之外的所有类,这个成员却是private。由于一个编译单元(即一个文件),只能隶属于一个包,所有经由包访问权限,处于同一个编译单元中的所有类彼此之间都是自动可访问的。

取得对某个成员的访问权的唯一途径是:

取得访问权限的方法
取得访问权限的方法

注意:同处于相同的目录但是没有给自己设定任何包名称的Java文件将被看做是隶属于该目录的默认包之中。

public:接口访问权限

使用关键字public,就意味着public之后紧跟着的成员声明自己对每个人(任何类)都是可用的(可访问的),尤其是使用类库的客户程序员更是如此。

private:你无法访问

关键字private的意思是,除了包含该成员的类之外,其他任何类都无法访问这个成员
注意:使用类的客户端程序员是无法访问包访问权限成员的。(这里意思感觉有点多余,其实可以不要?现在暂时不太懂
private的运用示例:可能想控制如何创建对象,并阻止别人直接访问某个特定的构造器(或全部构造器)。示例如下:

class Sundae {
  private Sundae() {}
  static Sundae makeASundae() {
    return new Sundae();
  }
}

public class IceCream {
  public static void main(String[] args) {
    //! Sundae x = new Sundae();
    Sundae x = Sundae.makeASundae();
  }
}

上述示例中,不能通过构造器来创建Sundae对象,而必须调用makeASundae()方法来达到此目的。

  • 说明:除非必须公开底层实现细目(此种境况很少),否则就应该将所有的域指定为private。

protected:继承访问权限

  • 如果创建了一个新包,并在该新包中创建一个类(子类)继承另一个包中的某个类(基类),那么唯一可以访问基类的成员就是其public成员和protected成员(当然,如果在同一个包内执行继承工作,就可以操纵所有的拥有包访问权限的成员)。
  • protected也提供包访问权限,即相同包内的其他所有类可以访问protected元素。
小结:访问权限示意图
 
访问权限示意图

4.接口和实现

  • 访问权限的控制常被称为是具体实现的隐藏。把数据和方法包装进类中,以及具体实现的隐藏,行共同被称作是封装。其结果是一个同时带有特征和行为的数据类型。
  • 为了清楚起见,可能会采用一种将public成员置于开头,后面紧跟protected、包访问权限和private成员的创建类形式。示例如下:
public class OrganizedByAccess {
  public void pub1() { /* ... */ }
  public void pub2() { /* ... */ }
  public void pub3() { /* ... */ }
  private void priv1() { /* ... */ }
  private void priv2() { /* ... */ }
  private void priv3() { /* ... */ }
  private int i;
  // ...
}

5.类的访问权限

  • 为了控制某个类的访问权限,修饰词必须出现于关键字class之前,如,public class Widget{...}
    类的一些限制如下:
    类的限制
    类的限制
  • 类既不可以是private(否则,除该类外,其他任何类都不可以访问它),也不可以是protected的。所以对类的访问权限,仅有两个选择包访问权限public。如果不希望其他人对该类用于访问权限,可以把所以的构造器都指定为private,从而阻止任何人创建该类的对象,但是有一个例外,就是你在该类的static成员内部可以创建该类的对象。示例如下:
class Soup1 {
  private Soup1() {}
  // (1) Allow creation via static method:
  public static Soup1 makeSoup() {
    return new Soup1();
  }
}

class Soup2 {
  private Soup2() {}
  // (2) Create a static object and return a reference
  // upon request.(The "Singleton" pattern):
  private static Soup2 ps1 = new Soup2();
  public static Soup2 access() {
    return ps1;
  }
  public void f() {}
}

// Only one public class allowed per file:
public class Lunch {
  void testPrivate() {
    // Can't do this! Private constructor:
    //! Soup1 soup = new Soup1();
  }
  void testStatic() {
    Soup1 soup = Soup1.makeSoup();
  }
  void testSingleton() {
    Soup2.access().f();
  }
}

说明

1)Soup1类和Soup2类展示了如何通过将所有的构造器指定为private来阻止直接创建某个类的实例。如果把该构造器指定为private,那么就谁也无法创建该类的对象了。但是现在别人该怎样使用这个类呢?

上面的例子就给出了两种选择:
a.在Soup1中,创建一个static方法,它创建一个新的Soup1对象并返回一个对它的引用。

  如果想要在返回引用前在Soup1上做一些额外的工作,或是如果想要记录到底创建了多少个Soup1对象(可能与限制其数量),这种做法将会大有裨益的。

b.Soup2用到了单例模式(singleton),这是因为我们始终只能创建它的一个对象。Soup2类的对象是作为Soup2的一个static private成员而创建的,所以有且仅有一个,而且除非是通过public方法access(),否则是无法访问到它的。

  • 注意:
    1)如果没有为类访问权限指定一个访问修饰符,它就会默认得到包访问权限。此时,即使将该类的构造器声明为public的,也不能在包外实例化该类。并且,即使该类中拥有static public字段或static public方法,也不能在包外直接通过该类访问。总之,在具有包访问权限的类中,使用public并不能将其修饰的成员或构造器提升到public权限,即使用public无效。

    2)一个类的默认构造器的访问权限和该类的访问权限相同。

    3)内部类可以是private或protected的。



原文地址:https://www.cnblogs.com/furaywww/p/8605003.html