Thinking in Java-访问权限控制

6.访问权限控制

6.1 包:库单元

一个java源代码文件,称为一个编译单元

单个编译单元中,只允许出现一个public类(可以存在多个非public类)

每个类都会生成一个.class文件

6.1.1 代码组织

  • 工作方式:Java可运行程序是一组可以打包并压缩为一个Java文档文件(JAR)的.class文件
  • 类库:一组类文件,使用关键字package。每个文件包含一个public类,任意数量的非public类(用于服务public类)
package
  • 规则

    • 必须为除文件注释外的第一句程序代码

    • 格式:package access

      代表该编译单元为access的类库的一部分

    • 全部使用小写字母

    • 使用import关键字导入指定类

      import access.mypackage.*;
      
  • package和import功能

    • 将单一的全局名字空间分割开,防止类名称冲突

6.1.2 创建唯一的包名

  • 包名组成

    • 第一部分是Internet域名的反顺序。
    • 第二部分为机器上的目录
  • CLASSPATH

    • 编译器碰到类库的import语句,会在CLASSPATH指定的目录中查找
  • 类的同名冲突

    • 情况:将两个包含相同名称的类库同时以*导入时,使用两个共有的类,将产生冲突

    • 解决方法:完全指明需要使用的类的位置

      // 假设两个类库都包含Vector类
      import net.value.*;
      import java.util.*;
      
      // 产生冲突的情况
      Vector v = new Vector();
      
      // 解决方法
      java.util.Vector v = new java.util.Vector();
      

6.1.3 定制工具库

public static void print(Object obj){
	System.out.println(obj);
}

6.1.4 用import改变行为

  • 条件编译:源代码中,部分代码在满足条件下才编译

  • 方法

    • 使用import改变行为

    • 使用判断条件为常量的if语句,根据if判断条件的真假,编译器直接把分支为false的代码块消除

      以下方法,final常量的代码块将消除

      // 空方法
      public void voidMethod(){
      
      }
      
      //final常量
      private final boolean FINAL_FLAG_FALSE = false;
      public void constantFalseFlag(){
          if(FLAG_FALSE){
              System.out.println("debug log...");
          }
      }
      
      // 非final
      private boolean  falseFlag= false;
      public void falseFlag(){
          if(falseFlag){
              System.out.println("debug log...");
          }
      }
      

6.2 Java访问权限修饰词

6.2.1 包访问权限

  • 规则
    • 不提供访问权限修饰词,代表“包访问权限”
    • “包访问权限”代表只有在同一个package中的成员,才能互相访问
  • 取得访问成员的途径
    1. 成员的访问权限修饰词为public
    2. “包访问权限”中,处于同一个包中的成员之间互相访问
    3. 通过继承的方式访问,继承而来的类允许访问public和protected成员,但不允许访问private成员
    4. 提供getter和setter方法访问,这是最优雅的方式,也是javabean的基本原理

6.2.2 public:接口访问权限

[外链图片转存失败(img-pytT6AHA-1563897704559)(/Users/toyz/Package/Note/Thinking in Java/Public访问权限.png)]

  • public任意成员皆可访问
默认包
  • 不提供访问修饰词,且在同一个folder中(非package中),会默认将类放置在“默认包”中,因此Cake可以创建Pie对象,调用f()方法

6.2.3 private:无法访问

  • 规则

    • 除包含该成员的类之外,任何其他类都无法访问这个成员
  • 用途

    • 是类的“助手”方法的方法。比如控制如何创建对象,阻止直接访问特定的构造器

    • 可以将类中的变量和方法用private修饰

      // 控制创建的对象
      Class Sundae{
        private Sundae(){}
        static Sundae makeSundae(){
          return new Sundae();
        }
      }
      
      public class IceCream{
        public static void main(String[] args){
          // 控制使用makeSundae()方法来创建对象
          Sundae s = Sundae.makeSundae();
        }
      }
      

6.2.3 protected:继承访问权限

  • 继承:利有现有类,也就是基类,将新成员添加到基类中而不需要修改基类的,还可以改变基类中现有成员的行为的方法

  • 规则

    • 继承类能够访问基类的protected成员
    • protected提供包访问权限
  • 注意点

    • protected是指子类可以访问、重写(即使不在同一个包中)。因此当子类继承基类,创建子类对象可以访问基类中的protected成员。而不是创建基类对象,访问基类中的protected成员。

    • 相同目录下,所有不具有明确package声明的文件,都视为默认包的一部分

      // 基类
      public class TestProtected {
          protected void pro(){};
      }
      
      // 子类
      public class TestAll extends TestProtected {
          public static void main(String[] args) {
              TestAll ta = new TestAll();
              ta.pro();
          }
      }
      
      public class TestAll {
          public static void main(String[] args) {
              // public 方法调用,成功,因为任意访问权限
              TestPublic tpub = new TestPublic();
              tpub.pub();
              // protected 方法调用,成功,因为包访问权限
              TestProtected tpro = new TestProtected();
              tpro.pro();
              // private 方法调用,失败
              TestPrivate tpri = new TestPrivate();
              // tpri.pri();
          }
      }
      

6.3 接口和实现

  • 封装:把数据和方法包装进类中,以及具体实现的隐藏

  • 访问控制权限将权限边界划在数据类型的内部原因

    1. 设定客户端程序员可以使用和不可以使用的边界
    2. 将接口和具体实现分离。客户端程序员仅可以向接口发送信息,防止破坏客户端代码

6.4 类的访问权限

  • 规则

    • 类的访问权限关键字必须出现在关键字class之前
  • 限制

    • 每个编译单元只能有一个public类

      因为编译的时候Java编译器会判断如果存在public类,该类当作这个编译单元的对外接口,类加载器需要把该类加载。

    • public的类名称必须和编译单元的文件名匹配,包括大小写

    • 存在编译单元内没有public类,因此可以随意命名文件——但不提倡

  • 注意点

    • 类的访问权限只有public和包访问权限两种

  • 当构造器为private时,如果创建对象

    • 方法一:创建一个static方法,方法创建对象,并返回引用

      class Soup1{
        private Soup1(){};
        public static Soup1 makeSoup1(){
          return new Soup1;
        }
      }
      
    • 方法二:单例模式,始终只能创建它的一个对象

      class Soup2{
      	private static Soup2 sp = new Soup2();
      	public static Soup2 access(){
          return sp;
        } 
      }
      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值