很多介绍Java语言的书籍(包括《Java编程思想》)都对protected介绍的比较的简单,基本都是一句话,就是: 被 protected 修饰的成员对于本包和其子类可见。这种说法有点太过含糊,常常会对大家造成误解。实际上,protected的可见性在于两点:

  • 基类的 protected 成员是包内可见的,并且对子类可见;
  • 若子类与基类不在同一包中,那么在子类中,子类实例可以访问其从基类继承而来的protected方法,而不能访问基类实例的protected方法。

我们可以通过以下几个关于protected方法可见性的例子来进一步掌握protected关键字。在碰到涉及protected成员的调用时,首先要确定出该protected成员来自何方,其可见性范围是什么,然后就可以判断出当前用法是否可行了,看下面七个例子:

实例 1

 1 package p1;
2 public class Father1 {
3 protected void f() {} // 父类Father1中的protected方法
4 }
5
6 package p1;
7 public class Son1 extends Father1 {}
8
9 package p11;
10 public class Son11 extends Father1{}
11
12 package p1;
13 public class Test1 {
14 public static void main(String[] args) {
15 Son1 son1 = new Son1();
16 son1.f(); // Compile OK ----(1)
17 son1.clone(); // Compile Error ----(2)
18
19 Son11 son = new Son11();
20 son11.f(); // Compile OK ----(3)
21 son11.clone(); // Compile Error ----(4)
22 }
23 }

对于上面的示例,首先看(1)(3),其中的f()方法从类Father1继承而来,其可见性是包p1及其子类Son1和Son11,而由于调用f()方法的类Test1所在的包也是p1,因此(1)(3)处编译通过。其次看(2)(4),其中的clone()方法的可见性是java.lang包及其所有子类,对于语句"son1.clone();"和"son11.clone();",二者的clone()在类Son1、Son11中是可见的,但对Test1是不可见的,因此(2)(4)处编译不通过。

实例 2

 1 package p2;
2 class MyObject2 {
3 protected Object clone() throws CloneNotSupportedException{
4 return super.clone();
5 }
6 }
7
8 package p22;
9 public class Test2 extends MyObject2 {
10 public static void main(String args[]) {
11 MyObject2 obj = new MyObject2();
12 obj.clone(); // Compile Error ----(1)
13
14 Test2 tobj = new Test2();
15 tobj.clone(); // Complie OK ----(2)
16 }
17 }

对于(1)而言,clone()方法来自于类MyObject2本身,因此其可见性为包p2及MyObject2的子类,虽然Test2是MyObject2的子类,但在Test2中不能访问基类MyObject2的protected方法clone(),因此编译不通过;对于(2)而言,由于在Test2中访问的是其本身实例的从基类MyObject2继承来的的clone(),因此编译通过。

实例 3

 1 package p3;
2 class MyObject3 extends Test3 {
3 }
4
5 package p33;
6 public class Test3 {
7 public static void main(String args[]) {
8 MyObject3 obj = new MyObject3();
9 obj.clone(); // Compile OK ------(1)
10 }
11 }

对于(1)而言,clone()方法来自于类Test3,因此其可见性为包p33及其子类MyObject3,而(1)正是在p33的类Test3中调用,属于同一包,编译通过。

实例 4

 1 package p4;
2 class MyObject4 extends Test4 {
3 protected Object clone() throws CloneNotSupportedException {
4 return super.clone();
5 }
6 }
7
8 package p44;
9 public class Test4 {
10 public static void main(String args[]) {
11 MyObject4 obj = new MyObject4();
12 obj.clone(); // Compile Error -----(1)
13 }
14 }

对于(1)而言,clone()方法来自于类MyObject4,因此其可见性为包p4及其子类(此处没有子类),而类Test4却在包p44中,因此不满足可见性,编译不通过。

实例 5

 1 package p5;
2
3 class MyObject5 {
4 protected Object clone() throws CloneNotSupportedException{
5 return super.clone();
6 }
7 }
8 public class Test5 {
9 public static void main(String[] args) throws CloneNotSupportedException {
10 MyObject5 obj = new MyObject5();
11 obj.clone(); // Compile OK ----(1)
12 }
13 }

对于(1)而言,clone()方法来自于类MyObject5,因此其可见性为包p5及其子类(此处没有子类),而类Test5也在包p5中,因此满足可见性,编译通过。

实例 6

1 package p6;
2
3 class MyObject6 extends Test6{}
4 public class Test6 {
5 public static void main(String[] args) {
6 MyObject6 obj = new MyObject6();
7 obj.clone(); // Compile OK -------(1)
8 }
9 }

对于(1)而言,clone()方法来自于类Test6,因此其可见性为包p6及其子类MyObject6,而类Test6也在包p6中,因此满足可见性,编译通过。

实例 7

 1 package p7;
2
3 class MyObject7 extends Test7 {
4 public static void main(String[] args) {
5 Test7 test = new Test7();
6 test.clone(); // Compile Error ----- (1)
7 }
8 }
9
10 public class Test7 {
11 }

对于(1)而言,clone()方法来自于类Object,因此该clone()方法可见性为包java.lang及其子类Test7,由于类MyObject7不在此范围内,因此不满足可见性,编译不通过。

Java protected 关键字详解的更多相关文章

  1. Java synchronized 关键字详解

    Java synchronized 关键字详解 前置技能点 进程和线程的概念 线程创建方式 线程的状态状态转换 线程安全的概念 synchronized 关键字的几种用法 修饰非静态成员方法 sync ...

  2. Java volatile关键字详解

    Java volatile关键字详解 volatile是java中的一个关键字,用于修饰变量.被此关键修饰的变量可以禁止对此变量操作的指令进行重排,还有保持内存的可见性. 简言之它的作用就是: 禁止指 ...

  3. Java Static关键字详解

    提起static关键字,相信大家绝对不会陌生,但是,想要完全说明白,猛的一想,发现自己好像又说不太明白... ...比方说,昨天被一个同学问起的时候... ... 当然,不是所有人都像我一样学艺不精的 ...

  4. Java static 关键字详解

    引言 在<Java编程思想>中有这样一段话:static方法就是没有this的方法.在static方法内部不能调用非静态方法,反过来是可以的.而且可以在没有创建任何对象的前提下,仅仅通过类 ...

  5. [java] java synchronized 关键字详解

    Java语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码.当两个并发线程访问同一个对象object中的这个加锁同步代码块时,一 ...

  6. Java this关键字详解

    this 关键字用来表示当前对象本身,或当前类的一个实例,通过 this 可以调用本对象的所有方法和属性.例如: public class Demo{ public int x = 10; publi ...

  7. Java Volatile 关键字详解

    原文链接:https://www.cnblogs.com/zhengbin/p/5654805.html 一.基本概念 先补充一下概念:Java 内存模型中的可见性.原子性和有序性. 可见性: 可见性 ...

  8. java final关键字详解

    final是java中保留关键字,可以声明成员变量.类.方法与本地变量,一旦引用final关键字,将不能再改变这个引用,编译器会检查代码,要是想改变该引用,会报错. final变量? 凡是对成员变量或 ...

  9. 《Java基础知识》Java this关键字详解

    this 关键字用来表示当前对象本身,或当前类的一个实例,通过this可以调用对象的所有方法和属性. 例如: public class Demo { private int x = 10; priva ...

  10. java关键字详解----static

    Java Static关键字详解   提起static关键字,相信大家绝对不会陌生,但是,想要完全说明白,猛的一想,发现自己好像又说不太明白... ...比方说,昨天被一个同学问起的时候... ... ...

随机推荐

  1. day07-OpenFeign-服务调用

    SpringCloud OpenFeign-服务调用 1.OpenFeign介绍 https://github.com/spring-cloud/spring-cloud-openfeign Open ...

  2. mybatis:Could not set parameters for mapping: ParameterMapping

    报错: 展开查看 org.apache.ibatis.exceptions.PersistenceException: ### Error querying database. Cause: org. ...

  3. C# 从0到实战 lambda表达式和Expression-bodied表达式

    什么是lambda表达式(λ表达式) 用过其他函数式语言的人可能对闭包和惰性计算很熟悉,没有用过的人也多多少少的听说过Lambda表达式.那么到底什么是lambda表达式呢?按我的看法是创建一个匿名的 ...

  4. 第2章. reco主题介绍

    1. 这是一个vuepress主题,旨在添加博客所需的分类.TAB墙.分页.评论等能: 2. 主题追求极简,根据 vuepress 的默认主题修改而成,官方的主题配置仍然适用: 3. 你可以打开 [午 ...

  5. 突破传统监测模式:业务状态监控HM的新思路

    作者:京东保险 管顺利 一.传统监控系统的盲区,如何打造业务状态监控. 在系统架构设计中非常重要的一环是要做数据监控和数据最终一致性,关于一致性的补偿,已经由算法部的大佬总结过就不在赘述.这里主要讲如 ...

  6. Istio数据面新模式:Ambient Mesh技术解析

    摘要:Ambient Mesh以一种更符合大规模落地要求的形态出现,克服了大多数Sidecar模式的固有缺陷,让用户无需再感知网格相关组件,真正将网格下沉为基础设施. 本文分享自华为云社区<华为 ...

  7. 卧槽Winform也可以这么好看?

    Winform也可以这么好看? 对于Winform很多人的刻板印象就是拖拉拽,简单生产界面,但是这样对于界面的效果,它并不会很好,虽然简单,快,但是效果也是极差,所以有很多人就去使用WPF,去写xml ...

  8. 2021-12-10:64位的浮点数和64位的有符号整数,哪个能表示的数据个数多? A.整型多。 B.浮点型多。 C.与平台有关。 D.一样多。 来自qq群。

    2021-12-10:64位的浮点数和64位的有符号整数,哪个能表示的数据个数多? A.整型多. B.浮点型多. C.与平台有关. D.一样多. 来自qq群. 答案2021-12-10: 答案选A. ...

  9. 2021-11-10:O(1) 时间插入、删除和获取随机元素。实现RandomizedSet 类:RandomizedSet() 初始化 RandomizedSet 对象。bool insert(in

    2021-11-10:O(1) 时间插入.删除和获取随机元素.实现RandomizedSet 类:RandomizedSet() 初始化 RandomizedSet 对象.bool insert(in ...

  10. 2021-10-18:乘积最大子数组。给你一个整数数组 nums ,请你找出数组中乘积最大的连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。力扣152。

    2021-10-18:乘积最大子数组.给你一个整数数组 nums ,请你找出数组中乘积最大的连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积.力扣152. 福大大 答案2021-1 ...