前面介绍子类继承父类的时候,提到了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. Oracle 函数 Function

    定义 函数用于计算和返回一个结果值,把经常需要进行的计算写成函数,函数的调用是表达式的一部分.     函数与过程在创建的形式上有些相似,也是编译后放在内存中供用户使用.     函数必须有一个返回值 ...

  2. Burp Suite Pro 教程

    1.Burp Suite Pro2.0.11破解版-2018.11.06更新 说明基地址 来源:http://ximcx.cn/post-110.html 启动;如果是用的burp2.0,把下面的代码 ...

  3. JDK、JRE

    JRE: java Runtime environment (java运行环境) JVM:java virtual machine (java 虚拟机) java程序就在jvm中运行. JDK: ja ...

  4. NFS部署文件共享

    本章解了如何配置网络文件系统(Network File System,NFS)服务来简化Linux系统之间的文件共享工作,以及通过部署NFS服务在多台Linux系统之间挂载并使用资源.在管理设备挂载信 ...

  5. 简单实用而不追求时髦的 Vim 配置

    前言 由于 Vim 的广泛流行,在网络上关于 Vim 的自定义配置汗牛充栋.既有高手 Tim Pope 的极简配置 tpope/vim-sensible(这个配置一个插件都没有),也有 spf13/s ...

  6. emWin酿造机过程演示,含uCOS-III和FreeRTOS两个版本

    第2期:酿造机过程演示 配套例子:V6-902_STemWin提高篇实验_酿造机过程演示(uCOS-III)V6-903_STemWin提高篇实验_酿造机过程演示(FreeRTOS) 例程下载地址:h ...

  7. storm集群架构

    一.storm何许人也? Storm 是Twitter的一个开源框架.Storm一个分布式的.容错的实时计算系统,它被托管在GitHub上,遵循 Eclipse Public License 1.0. ...

  8. [Swift]LeetCode186. 翻转字符串中的单词 II $ Reverse Words in a String II

    Given an input string, reverse the string word by word. A word is defined as a sequence of non-space ...

  9. [Swift]LeetCode669. 修剪二叉搜索树 | Trim a Binary Search Tree

    Given a binary search tree and the lowest and highest boundaries as L and R, trim the tree so that a ...

  10. [Swift]LeetCode792. 匹配子序列的单词数 | Number of Matching Subsequences

    Given string S and a dictionary of words words, find the number of words[i] that is a subsequence of ...