受保护的(protected)——声明该成员的类的子类可以访问这个类的成员(但有一定的限制),并且,声明该成员的包内部的任何类也可以访问这个成员

protected修饰符参考:http://www.360doc.com/content/12/0529/09/10042054_214421414.shtml  

今天在看《Effective java》(第二版)的发现一个困扰我的问题,条目:第17条  要么为继承而设计,并提供文档说明,要么就禁止继承

看到java.util.ArrayList中的removeRange(int fromIndex,int toIndex)方法

removeRange(int fromIndex,int toIndex)方法的定义是从此列表中移除索引在fromIndex(包括)和toIndex(不包括)之间的所有元素。

于是自己就写了一个测试,如下:

import java.util.*;
public class TestRemoveRange1{
public static void main(String args[]){
ArrayList<Integer> list = new ArrayList<>();
for(int i=0;i<10;i++){
list.add(i);
}
//删除0 - 6(不包括6)的元素
list.removeRange(0,6);
System.out.println(list);
}
}

但是运行时报错。

于是查看API,发现removeRange(int fromIndex,int toIndex)方法是protected ,我心想难道是list.removeRange(2,4)调用有错。

解决方法一:写了下一版本,如下:

import java.util.*;
public class TestRemoveRange2<E> extends ArrayList<E>{
public static void main(String args[]){
TestRemoveRange2<Integer> list = new TestRemoveRange2<>();
for(int i=0;i<10;i++){
list.add(i);
}
//删除0 - 6(不包括6)的元素,编译能过
list.removeRange(0,6);
System.out.println(list);
}
}

输出的结果如我所料:[6,7,8,9]

解决方法二:用subList(int fromIndex,int toIndex).clear();代码如下:

import java.util.*;
public class TestRemoveRange3{
public static void main(String args[]){
ArrayList<Integer> list = new ArrayList<>();
for(int i=0;i<10;i++){
list.add(i);
}
//删除0 - 6(不包括6)的元素
list.subList(0,6).clear();
System.out.println(list);
}
}

输出结果也是:[6,7,8,9]

于是我对protected关键字有了很大的疑惑,学了那么久的java,我从理论上知道protected是一个包内部的类,成员变量,方法可访问。但是现在遇到这个问题,我不知道怎么解释它是怎么形成的了。这里就说明protected修饰符还是有一些微妙的地方。在网上找了一篇比较好的博文了解了一下protected这个类的微妙...

com.cwnu.test1包中有:

package com.cwnu.test1;
public class SuperClass {
protected void method(){
System.out.println("This is SuperClass method");
}
}
package com.cwnu.test1;
/**
* 同一个包下,父类protected方法对同一包中的类是可见的
*/
public class SubClass1 extends SuperClass{
public static void main(String[] args) {
SuperClass sc = new SuperClass();
sc.method(); //success
SubClass1 sc1 = new SubClass1();
sc1.method(); //success
SubClass2 sc2 = new SubClass2();
sc2.method(); //success
}
}
class SubClass2 extends SuperClass{
}

如果修改了代码,在两个不同的包中测试protected的访问权限,例子如下:

package com.cwnu.test1;
public class SuperClass {
protected void method(){
System.out.println("This is SuperClass method");
}
}

SuperClass类还是不变

package com.cwnu.test2;

import com.cwnu.test1.SuperClass;

public class SubClass2 extends SuperClass{
public static void main(String[] args) {
SuperClass sc = new SuperClass();
/**
* sc.method();
* 上面的方法不能编译通过,因为SuperClass类的实例在其他包(package com.cwnu.test2)
* 中调用包test1中自己定义的由protected修饰的method()方法,方法是不可见的
**/
SubClass2 sc2 = new SubClass2();
sc2.method();
SubClass3 sc3 = new SubClass3();
sc3.method();
}
}
class SubClass3 extends SuperClass{
/**
* 重写了父类SuperClass的method()方法
* 如果不重写父类的method()方法,用sc3.method()调用编译不会通过,方法也是不可见的
*/
protected void method(){
System.out.println("This is SubClass3 method()");
}
}

我想这也就解释了上面为什么ArrayList的实例list想调用removeRange(int fromIndex,int toIndex)方法不能编译通过的原因——不可见的

也解释了通过继承ArrayList而子类能访问removeRange(int fromIndex,int toIndex)这个方法的原因(详细见TestRemoveRange2)

打开ArrayList源码发现,调用SubList(int fromIndex,int toIndex)最终还是调用了removeRange(int fromIndex,int toIndex)的实现。

removeRange(int fromIndex,int toIndex)内部的删除还是通过移位这一经典的删除方法实现的。

【初学者常见问题】一脚踏入protected埋下的陷阱的更多相关文章

  1. JDK动态代理给Spring事务埋下的坑!

    一.场景分析 最近做项目遇到了一个很奇怪的问题,大致的业务场景是这样的:我们首先设定两个事务,事务parent和事务child,在Controller里边同时调用这两个方法,示例代码如下: 1.场景A ...

  2. (转)面试必备技能:JDK动态代理给Spring事务埋下的坑!

    一.场景分析 最近做项目遇到了一个很奇怪的问题,大致的业务场景是这样的:我们首先设定两个事务,事务parent和事务child,在Controller里边同时调用这两个方法,示例代码如下: 1.场景A ...

  3. 处理器在 protected mode 下的 protection

    前言 实模式,保护模式,分段,分页,虚拟内存,内核态,用户态,如果你对这些术语之间的关系非常熟悉,那就不用继续看了.这篇主要记录我对用户态/内核态的一些理解,如有不对还请指教. 下述说明均为 x86- ...

  4. 关于sails 初学者常见问题汇总

    http://sailsdoc.swift.ren/ 这里有 sails中文文档 一.安装时: 先装nodejs,成功标志 node -v 安装sails 全局安装 node install sail ...

  5. mysql中now()函数的使用,还有oracle的sysdate,可能埋下的坑

    mysql中now()函数的使用,还有oracle的sysdate 在需求中如果系统中药添加当前操作的时间那么很简单的一个操作在写sql的时候直接在这个字段对应的位置写上now()函数就可以了,这样就 ...

  6. 路由页面缓存开启 以及 keep-alive 给你埋下的坑

    为什么要用keep-alive呢, 因为这个会缓存dom模板, 下次再回到这个页面, 就可以利用这个已经渲染好的dom结构了, 如果数据不一样, 也会启用 virtualDoM 进行diff更新, 这 ...

  7. webpack学习笔记(二)-- 初学者常见问题及解决方法

    这篇文章是webpack学习第二篇,主要罗列了本人在实际操作中遇到的一些问题及其解决方法,仅供参考,欢迎提出不同意见. 注:本文假设读者已有webpack方面相关知识,故文中涉及到的专有名词不做另外解 ...

  8. 【持续更新】.Net 开发中给自己埋下的坑!

    1.文件“XXX”正在由另一进程使用,因此该进程无法访问此文件. 原因剖析:文件在主线程操作,在子线程中读写操作文件,刚开始没有意识到程序的问题所在,总是在FileStream中报错,google后常 ...

  9. [开发笔记]--把input框设置成font-size:0埋下的坑。

    vue项目上开发了一个输入pin码的组件.在某些安卓机器上.用户点击键盘后会自动失去焦点自动收起键盘.经过排查,发现是css属性font-size设置成0导致的.

随机推荐

  1. HibernateProxy异常处理 java.lang.UnsupportedOperationException: Attempted to serialize java.lang.Class: org.hibernate.proxy.HibernateProxy. Forgot to register a type adapter?

    这里使用google的Gson包做JSON转换,因为较早的1.4版本的FieldAttributes类中没有getDeclaringClass()这个方法,这个方法是获取field所属的类,在我的排除 ...

  2. Lua 基础知识-面向对象

    通过函数闭包的方式来实现面向对象 -- 通过函数闭包的方式来实现面向对象 function People(name) local self = {} local function init() sel ...

  3. php视图操作

    一.视图的基本介绍          视图是虚拟的表.与包含数据的表不一样,视图只包含使用时动态检索数据的查询.         使用视图需要MySQL5及以后的版本支持.         下面是视图 ...

  4. Python文件之----CSV

    # -*- coding:utf-8 -*- ''' Created on 2015年4月20日 @author: liuxue ''' import csv import sys reload(sy ...

  5. HDU 3721 Building Roads (2010 Asia Tianjin Regional Contest) - from lanshui_Yang

    感慨一下,区域赛的题目果然很费脑啊!!不过确实是一道不可多得的好题目!! 题目大意:给你一棵有n个节点的树,让你移动树中一条边的位置,即将这条边连接到任意两个顶点(边的大小不变),要求使得到的新树的直 ...

  6. 10.使用final关键字修饰一个变量时...

    10.使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变? 答:引用不能变,不能将引用再次指向另一个新的对象,但引用所指向的对象中的内容是可以改变的. 补充: 1.对于基本类型,f ...

  7. CSS定位与浮动

    定位的基本思想很简单,它允许你定义元素框相对于其正常位置应该出现的位置,或者相对于父元素.另一个元素甚至浏览器窗口本身的位置.显然,这个功能非常强大,也很让人吃惊.要知道,用户代理对 CSS2 中定位 ...

  8. C盘hosts

    # Copyright (c) - Microsoft Corp. # # This is a sample HOSTS file used by Microsoft TCP/IP for Windo ...

  9. FCKEditor的用法(asp版)

    1:下载FCKEditor 去www.baidu.com 搜索,我本来想上传的,但不知道怎么传.下载下来后解压到你网站的目录,最好就放在根目录下,文件夹名字就用FCKEditor:这里可以随便自己喜好 ...

  10. Microsoft OLE DB Provider for SQL Server 错误 '80040e21'

    我的是因为数据库满了,正在向服务商申请增加数据库容量 原文地址:Microsoft OLE DB Provider for SQL Server 错误 '800作者:欧阳IT记事本 昨天打开网站还正常 ...