前面介绍子类继承父类的时候,提到了public(公共)和private(私有)两个修饰符,其中public表示它所修饰的实体是允许外部访问的;而private表示它所修饰的实体不允许外部访问,只能在当前类内部访问private成员,即便是子类也不能访问父类的私有成员。这种情况就令人产生了困惑,私人财产当然不会给外人,可是为啥连儿子都无法动用老子的财物呢?看起来public与private的规则不甚合理,毕竟儿子同外人还是有区别的呀,所谓亲疏有别、一家人不说两家话。为此Java设计了新的修饰符名叫protected,意思是受保护的,其实就是给子类们网开一面,凡是被protected修饰的成员,外部仍然不可访问,唯有从当前类派生而来的子类可以访问。那么对于受保护的成员来说,它对外部而言如同私有成员一样不能访问,它对子类而言如同公共成员一样能够访问。
当然,引入protected不仅仅是面子上好看,还带来了实实在在的好处。比如之前编写鸭子类继承鸟类的时候,发现性别名称字段需要由“雄/雌”改为家禽通用的“公/母”,当时尝试了下列的两种写法:
1、在Duck类里面重新定义与父类同名的属性字段sexName,这样没有变更外部对sexName的访问权限,但是需要重写与该字段有关的所有方法。
2、把Bird类的sexName改为使用public修饰,此时新的鸭子类DuckPublic无需全部重写相关方法,但同时外部变得能够直接读写sexName字段,从而破坏了原来Bird类对该字段的良好封装。
既要保持外部的访问权限不变,又要避免子类冗余的方法重载,这两个愿景看似鱼与熊掌不可兼得。现在有了修饰符protected,原本自相矛盾的问题立马迎刃而解,具体的解决步骤说明如下:
首先给Bird类的sexName属性添加protected修饰,表示该字段是受保护的成员属性,只可在本家族内部使用,不可对外部开放。于是改写后的Bird类代码片段如下所示:

public class Bird {

	// 此处省略其它成员的定义……

	// 定义鸟的性别名称
//private String sexName; // 与Duck搭配使用
//public String sexName; // 与DuckPublic搭配使用
protected String sexName; // 与DuckProtected搭配使用 // 此处省略其它成员的定义……
}

接着编写与之配套的鸭子类代码DuckProtected,并重载setSexType方法,将sexName字段的取值改为“公”或者“母”。详细的DuckProtected类定义代码示例如下:

// 演示关键字protected的用法
public class DuckProtected extends Bird { public DuckProtected(String name, int sex) {
super(name, sex, "嘎嘎");
} public void setSexType(int sexType) {
super.setSexType(sexType);
// 若想对父类的属性直接赋值,又不想对外开放该属性,则可将父类的属性从private改为protected
// 被protected修饰的成员,表示受保护,它允许子类访问,但不允许外部访问。
// 倘若父类的属性被protected修饰,则子类可以直接读写该属性;
// 倘若父类的方法被protected修饰,则子类可以直接读写该方法;
// 所谓读方法,就是方法的调用操作;所谓写方法,就是方法的重载操作。
sexName = (sexType==0) ? "公" : "母";
//super.sexName = (sexType==0) ? "公" : "母";
}
}

注意,被protected修饰的成员属性,对于子类来说可读可写,既能把原值读出来也能把新值写进去。然而被protected修饰的成员方法,又何来所谓的读写操作?确实,方法不像字段,它没有读方法和写方法的概念,只有方法调用和方法重载的说法。那么对于方法而言,方法调用可看作是一种读操作,而方法重载可看作是一种写操作,瞅瞅“重写”二字带着一个“写”字嘛。

从公共的public,到私有的private,再到受保护的protected,正好三个单词都以字母p开头,3p系列这下总算凑齐了吧?可是还有一种情况,就是某个实体不加任何的开放性修饰符。嗯哼,Java居然允许某个东西既非公共又非私有也非受保护,那这东东究竟要给谁使用?不加修饰符的话,其实Java也给它分配了一个默认的开放性,譬如某人在美国出生,他便自动获得了美国国籍;某人在北京出生,理应要获得北京户口,这个国籍或户口即可看成是默认的归属地。拥有北京户口的人,可以优先享受当地的教育、医疗等资源,为的就是他/她是北京人,所以当地资源对他/她够友好。在Java的编程世界之中,“当地”指的是同一个package(代码包),既然大家生活在同一个package的屋檐下面,就应当互相帮助互相爱护。因而未加3p修饰符的实体,表示它属于当地资源,对当地人很友好,凡是有当地户口的都允许访问它。
如此算来,Java实际上存在四种开放性,根据开放程度的大小排序,依次分别为:
public:公共的,允许所有人访问;
无修饰符:友好的,允许当地人访问;
protected:受保护的,允许本家族访问,包括自身及其子类;
private:私有的,只有自身可以访问。

更多Java技术文章参见《Java开发笔记(序)章节目录

Java开发笔记(五十)几种开放性修饰符的更多相关文章

  1. Java开发笔记(十八)上下求索的while循环

    循环是流程控制的又一重要结构,“白天-黑夜-白天-黑夜”属于时间上的循环,古人“年复一年.日复一日”的“日出而作.日落而息”便是每天周而复始的生活.计算机程序处理循环结构时,给定一段每次都要执行的代码 ...

  2. Java学习笔记(4)----Public,Protected,Package,Private修饰符可见性

    Java修饰符类型(public,protected,private,friendly) public的类.类属变量及方法,包内及包外的任何类均可以访问:protected的类.类属变量及方法,包内的 ...

  3. java学习笔记12(final ,static修饰符)

    final: 意思是最终的,是一个修饰符,有时候一个功能类被开发好了,不想被子类重写就用final定义, 用final修饰的最终数据成员:如果一个类的数据成员用final修饰符修饰,则这个数据成员就被 ...

  4. Java学习笔记:04面向对象-内部类_访问修饰符_final

    04面向对象-内部类/访问修饰符/final 1.static的介绍 static:关键字,静态的 static的作用是用来修饰类中的成员 2.访问一个类中的某一个成员变量 方法一: _1.创建对象 ...

  5. Java开发笔记(十四)几种运算符的优先级顺序

    到目前为止,我们已经学习了Java语言的好几种运算符,包括算术运算符.赋值运算符.逻辑运算符.关系运算符等基础运算符,并且在书写赋值语句时都没添加圆括号,显然是默认了先完成算术.逻辑.关系等运算,最后 ...

  6. Java开发笔记(十五)短路逻辑运算的优势

    前面提到逻辑运算只能操作布尔变量,这其实是不严谨的,因为经过Java编程实现,会发现“&”.“|”.“^”这几个逻辑符号竟然可以对数字进行运算.譬如下面的代码就直接对数字分别开展了“与”.“或 ...

  7. Java开发笔记(十九)规律变化的for循环

    前面介绍while循环时,有个名叫year的整型变量频繁出现,并且它是控制循环进出的关键要素.不管哪一种while写法,都存在三处与year有关的操作,分别是“year = 0”.“year<l ...

  8. Java开发笔记(十二)布尔变量论道与或非

    在编程语言的设计之初,它们除了可以进行数学计算,还常常用于逻辑推理和条件判断.为了实现逻辑判断的功能,Java引入了一种布尔类型boolean,用来表示“真”和“假”.该类型的变量只允许两个取值,即t ...

  9. Java开发笔记(十六)非此即彼的条件分支

    前面花了大量篇幅介绍布尔类型及相应的关系运算和逻辑运算,那可不仅仅是为了求真值或假值,更是为了通过布尔值控制流程的走向.在现实生活中,常常需要在岔路口抉择走去何方,往南还是往北,向东还是向西?在Jav ...

随机推荐

  1. CentOS 编译安装 Nodejs (实测 笔记 Centos 7.3 + node 6.9.5)

    环境: 系统硬件:vmware vsphere (CPU:2*4核,内存2G,双网卡) 系统版本:CentOS-7.0-1406-x86_64-DVD.iso 安装步骤: 1.准备 1.1 显示系统版 ...

  2. MySQL视图更新

    昨天在写美团2019秋招笔试题的时候遇到了关于视图是否能更新的问题,突然感觉这个问题之前复习的时候重点关注过,但是却又想不全.今天特地搜了一些资料总结一下.本文主要说明视图的更新限制,如需关于视图的更 ...

  3. LSI IBM服务器阵列卡操作经历

    说明:因为服务器的一个磁盘坏了,因为没有经验不敢操作.正好有一台撤下来的相同服务器,所以查找了各种教程,研究了一下各种操作.记录在这里,防止忘记.一.概念说明raid(自己百度)阵列卡组(group) ...

  4. linux操作命令之帮助命令

    一.man命令的帮助: man 命令名 获取指定命令的帮助 例如man ls 查看ls的帮助 man man可以看到man有8个级别的man帮助命令使用场景 1.查看命令的帮助 2.查看可被内核调用的 ...

  5. SUSE12Sp3-Supervisor 守护.net core进程

    1.安装setuptools 将setuptools-0.6c11.tar.gz安装包放到服务器上 tar zxvf setuptools-0.6c11.tar.gz cd setuptools-0. ...

  6. [Swift]LeetCode188. 买卖股票的最佳时机 IV | Best Time to Buy and Sell Stock IV

    Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...

  7. [Swift]LeetCode674. 最长连续递增序列 | Longest Continuous Increasing Subsequence

    Given an unsorted array of integers, find the length of longest continuous increasing subsequence (s ...

  8. [Swift]LeetCode828. 独特字符串 | Unique Letter String

    A character is unique in string S if it occurs exactly once in it. For example, in string S = " ...

  9. 在 ns-3.25中添加 plc(电力线载波) 模块

    上一篇安装好了 ns-3.25,这里继续往里添加 plc 模块.整理之前现推荐一个网站,大家可以参考. 英属哥伦比亚大学(University of British Columbia,UBC)提供NS ...

  10. SpringBoot 集成Mybatis 连接Mysql数据库

    记录SpringBoot 集成Mybatis 连接数据库 防止后面忘记 1.添加Mybatis和Mysql依赖 <dependency> <groupId>org.mybati ...