• xianaldai

    本期是Java开发教程系列的第四期,本期主要向各位介绍*访问控制*——规定类里的成员能被谁访问.若你已经熟悉四种访问级别[public/protected/包私有(package-private)/private],可以跳过本期内容.

    *每期叠甲*:

    时间仓促,水平有限,文中难免存在缺点和错误,恳请广大开发者和从业者指正.


    *一、为什么要控制访问*

    第 3 期我们为了让跨包能用,把字段和方法都标了 public.但全部 public 有问题:```

    public class Student {

    public double score;

    }

    Student s = new Student();

    s.score = -80; // 成绩居然是负数?!
    ```成绩为负明显不合理.可字段是 public 的,任何代码都能随便改,拦不住.

    *访问控制*就是为了解决这个问题:规定类里的每个成员*能被谁访问*.把不该让别人乱动的数据藏起来,只留几个安全的口子让外面用——这个"藏起来"的做法叫*封装*,下一期专门讲,本期先把"谁能访问谁"这张规则表讲透.


    *二、四种访问级别*

    Java 的成员有四种访问级别,从"最开放"到"最封闭":

    图片

    用一张"同包/子类/任意位置"的表格更清楚:

    图片

    记忆口诀:*越往后越封闭*.

    - public:谁都能用,包括跨包

    - protected:同包能用 + *不同包的子类*也能用(这一档只比默认多开一个口子)

    - 默认(包私有):*只有同一个包*能用,名字叫"包私有"(package-private)

    - private:*只有本类内部*能用,连同包都碰不到

    四个级别从"完全公开"到"完全私有",一行一行对比着记,别死背.


    *三、动手验证:访问边界实验*

    光看表容易忘,亲手让编译器报几次错就记住了.做一个两个包 + 一个子类的小实验.

    目录结构:```

    codes/

    └── src/

    ├── com/mycodes/model/ ← 包 com.mycodes.model

    │ ├── Student.java

    │ └── StudentSub.java ← 子类,在另一个包

    └── com/mycodes/app/ ← 包 com.mycodes.app

    └── Main.java
    ``文件一 com/mycodes/model/Student.java:``

    package com.mycodes.model;

    public class Student {

    public String name; // public:任何地方都能访问

    String nickname; // 默认:只有同包能访问

    private String secret; // private:只有本类能访问

    protected void printDetail() { // protected:同包 + 子类

    System.out.println(name + "(" + nickname + ")");

    }

    }
    ``文件二 com/mycodes/model/StudentSub.java(不同包的子类):``

    package com.mycodes.model;

    public class StudentSub extends Student {

    public void test() {

    System.out.println(name); // public,子类能用

    System.out.println(nickname); // 同包(子类和父类同包)

    // System.out.println(secret); // private,子类也碰不到

    printDetail(); // protected,子类能用

    }

    }
    ``文件三 com/mycodes/app/Main.java(同包外、非子类):``

    package com.mycodes.app;

    import com.mycodes.model.Student;

    public class Main {

    public static void main(String\[\] args) {

    Student s = new Student();

    System.out.println(s.name); // public,跨包也能用

    // System.out.println(s.nickname); // 默认,跨包不能用

    // System.out.println(s.secret); // private,更不能

    // s.printDetail(); // protected,跨包且不是子类

    }

    }
    ```*动手验证*:把每处注释掉的代码一行一行放开,编译,看报错——报错信息会直说"访问权限不足".全部放开的报错顺序,正好就是表格从右往左读一遍.看完报错再把代码注释回去,项目就能跑.


    *朝花夕拾:第 3 期留的半个规则,本期补全了*

    第 3 期我们只讲了两个:public 任何地方能访问、默认只有同包能访问,当时说"完整的四种访问级别下一期专门讲".现在四档齐了:

    - protected 比默认*多*的口子:不同包的*子类*

    - private 比默认*少*的口子:连*同包*都不行

    记住一个关系图:public > protected > 默认 > private.第 3 期你写的 public class Student + public 字段,今天开始,字段就可以放心地往"更封闭"的方向收了.


    *总结*

    本期把"谁能访问谁"讲清楚了:

    - *四种访问级别*:public > protected > 包私有 > private,越往后越封闭

    - *protected*:同包 + 不同包子类可用

    - *包私有*:只有同包可用

    - *private*:只有本类可用

    - 动手做了一遍"放开注释看编译报错"的访问边界实验

    下一期我们学习*封装与 static*——用 private + getter/setter 把数据保护起来,再认识"属于类而不属于对象"的 static.

    主楼
  • Jarvis-d

    还在学习古法吗?感觉不如研究怎么驯服 AI

    #1
  • Howryann

    粗略学完直接快进到 Springboot,但现在更应该多研究一下 ai

    #2
  • bitwang

    全忘光了,如果面试问这个估计答不出来,哈哈哈,现在都是ai一把梭哈了

    #3
  • 雾隐楼台

    好久没看到这种古法教程了,现在还会问这些吗

    #4
  • xuanxuan

    凭实力刷到4帖,我建议佬友在文档共建里面将内容汇总成为1帖然后加目录,就不怕帖子超时编辑。

    #5

发表回复

登录后回复