Java访问权限控制的深入理解

面向对象设计的2个基本问题:

  1. 如何把变动的部分与保持不变的部分区别开来?
  2. 开发者如何约定权限来修改和改进代码,并确保客户代码不会因为这些改动收到影响?

Java使用访问权限修饰符来供开发人员向客户端程序员指明可用和不可用的,以及访问权限控制等级:

  • 包访问权限(没有修饰符关键词)
  • public - 公开的
  • protected - 保护的
  • private - 私有的

Java中构建类库的概念以及对于谁有权限取用该类库的控制问题,使用 package 方式控制。

1. 包:库的单元

包内有一组类,他们在单一的名字空间之下组织在一起。
如Java在标准发布中有一个工具库,被组织在java.util名字空间下,java.util中有一个叫ArrayList的类,使用ArrayList的方式有两种:

  • 全限定名:
java.util.ArrayList list = new java.util.ArrayList();
  • 导入包名:
import java.util.*;  // 导入util下所有工具类(通配符 * )
import java.util.ArrayList; // 导入util下ArrayList工具类

为了防止类名称之间的冲突问题:
一个java源代码文件通常被称为编译单元,.java为后缀名,该类名必须与文件名相同,且编译单元内只能有一个public类,否则Java编译器不会通过编译。
该public类在包之外是无法被看到和使用。
Java的解释器负责编译器生成的.class文件的查找、装载、和解释。

如果希望构件(独立成对的.java和.class)从属于同一个群组,就可以使用关键字:

package access; 
// 必须文件第一行,表示声明该文件是名为access的类库的一部分
// 在该文件下的public类使用时,必须使用全限定名或者import导入包

Java包的命名规则为:全小写字母。

2. Java访问权限修饰词

Java 有三个显式关键字来设置类中的访问权限:public(公开),private(私有)和protected(受保护)。这些访问修饰符决定了谁能使用它们修饰的方法、变量或类。

  • public(公开)表示任何人都可以访问和使用该元素;
  • private(私有)除了类本身和类内部的方法,外界无法直接访问该元素。private 是类和调用者之间的屏障。任何试图访问私有成员的行为都会报编译时错误;
  • protected(受保护)类似于 private,区别是子类(下一节就会引入继承的概念)可以访问 protected 的成员,但不能访问 private 成员;
  • default(默认)如果你不使用前面的三者,默认就是 default 访问权限。default 被称为包访问,因为该权限下的资源可以被同一包(库组件)中其他类的成员访问。
2.1 public

声明之后紧跟着的成员时每个人都可用的,尤其是使用类库的客户程序员更是如此。

package access.dessert;
public class Cookie {
    public Cookie() { //公开的
        System.out.println("Cookie constructor");
    }
    void bite() { //非公开,默认的
        System.out.println("bite");
    }
}
import access.dessert.*;
public class Dinner {
    public static void main(String[] args) {
        Cookie x = new Cookie(); //可以访问
        // x.bite();  // 不能访问,因为权限非public
    }
}
  1. Cookie.java必须位于名为access下的dessert目录中
  2. 不同目录下创建了Dinner.java就可以通过import导包的形式方位到 Cookie
  3. Dinner.java对于非public的bite()方法是不能访问的,编译器也禁止使用它
2.2 private

除了包含该成员的类以外的地方都无法直接访问这个修饰符修饰的成员。

  • 修饰成员变量:只能通过get/set成员方法访问
  • 修饰成员方法:该成员方法仅类内可以访问
  • 修饰构造方法:该类不允许使用该私有构造方法来创建对象
public class Test01 {
    public static void main(String[] args) {
        //MyClass m = new MyClass();  // Error: private MyClass() {}
        MyClass m = new MyClass(10);
        m.setA(20);
        //System.out.println(m.getA()); // Error
    }
}
class MyClass {
    private int a; //私有
    private MyClass() {} //私有
    public MyClass (int n) {
        this.a = n;
    }
    private int getA() { //私有
        System.out.println(this.a);
        return a;
    }
    public void setA(int a) {
        this.a = a;
        this.getA();
    }
}
2.3 protected

关键字protected处理的是继承的概念,通过继承可以利用一个现有类(父类),然后将新成员添加到该父类而不必去修改父类,还可以改变父类的现有成员的行为。——方法覆盖。

  1. 如果创建了一个新包,并再另一个包中继承类,那么唯一可以访问的成员就是源包的public成员;
  2. 如果父类的创建者会希望有某个特定的成员,把对它的访问权限赋予派生类而不是所有类,这就需要protected修饰。
  • protected提供包访问权限,即相同包内的其他类可以访问protected元素

3. 接口和实现中的访问权限

封装思想,即把数据和方法包装进类内,以及具体实现的隐藏,共同被称作封装。

访问权限的边界放在了数据类型内部的原因:

  1. 要设定客户端程序员可以使用和不可以使用的界限;
  2. 将接口和具体实现进行分离。

【常用做法】将public成员置于类的开头部分,后面跟着protected、包访问权限和private成员的创建类形式。
(好处:类的使用者可以首先阅读到重要的部分)

class Access {
    public void m1() { }
    public void m2() { }
    
    protected void o1() { }
    protected void o2() { }
    
    private void p1() { }
    private void p2() { }
    
    private int a;
    private int b;
    //...
}

4. 类的访问权限

原则:

  1. 每个.java源文件必须只能有一个public类;
  2. public类的名称必须与该源文件的文件名一致;
  3. .java的源文件中不带public类也是可以的,此时可以随意对文件命名(但随意命名会导致可读性变得非常差!谨慎)且文件中没有访问权限修饰符的类默认为 包访问权限,这也意味着该类的对象可以由包内任何其他类来创建,但在包外则不行;
  4. 如果默认无访问权限修饰符修饰的类的某个static成员是public的话,则客户端程序员仍然可以调用该static成员,尽管他们并不能生成该类的对象(类加载)。

注意:
访问权限控制,专注于类库创建者和该类库的外部使用者之间的关系,这种关系也是一种通信方式。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,463评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,868评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,213评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,666评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,759评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,725评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,716评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,484评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,928评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,233评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,393评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,073评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,718评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,308评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,538评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,338评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,260评论 2 352