很多介绍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. ARouter源码分析

    源码看过好几遍了,但是总是会忘记,特此记录下 先从注解处理器开始 BaseProcessor是其他三个注解处理器的抽象类,子类去实现process方法.在其中的init方法中会获取我们的module模 ...

  2. FormData收集表单信息&并且转化为Json格式进行提交验证

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. 使用Dockerfile构建容器镜像

    Dockerfile官方文档: https://docs.docker.com/engine/reference/builder/ 获取容器镜像的方法 容器镜像是容器模板,通过容器镜像才能快速创建容器 ...

  4. win10启动docker报错,错误码 0xffffffff

    一.注册表修复(如果有就不用管) 在\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WinSock2\Parameters\AppId_Ca ...

  5. JAVA注解@Scheduled 不执行

    spring boot项目需要在启动类加上注解 @EnableScheduling 定义一个接口 StockTask.java 1 public interface StockTask { 2 pub ...

  6. RTSP Server(LIVE555)源码分析(四)-SETUP信令

    主要分析RTSPServer::RTSPClientSession针对客户端SETUP事件处理 一. SETUP信令,handleCmd_SETUP源码解析 1)步骤1.03,parseTranspo ...

  7. 沁恒 CH32V208(一): CH32V208WBU6 评估板上手报告和Win10环境配置

    目录 沁恒 CH32V208(一): CH32V208WBU6 评估板上手报告和Win10环境配置 CH32V208 CH32V208系列是沁恒32位RISC-V中比较新的一个系列, 基于青稞RISC ...

  8. Java代码读取properties配置文件

    读取properties配置文件 package com.easycrud.utils; import java.io.IOException; import java.io.InputStream; ...

  9. 【Redis】Redis 编译安装配置优化,多实例配置

    一.Redis 配置详解 # Redis configuration file example. # # Note that in order to read the configuration fi ...

  10. 万字长文详解如何使用Swift提高代码质量

    前言 京喜APP最早在2019年引入了Swift,使用Swift完成了第一个订单模块的开发.之后一年多我们持续在团队/公司内部推广和普及Swift,目前Swift已经支撑了70%+以上的业务.通过使用 ...