• 【初学者常见问题】一脚踏入protected埋下的陷阱


    受保护的(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)内部的删除还是通过移位这一经典的删除方法实现的。










  • 相关阅读:
    Qt编写物联网管理平台35实时曲线
    Qt开发经验小技巧221225
    Qt编写物联网管理平台36通信协议
    Qt编写物联网管理平台34地图按钮
    【Python】抛砖引玉连续有序数组的排序问题
    java经验总结
    0618
    面试_子数组类问题
    【segmentation fault】vsnprintf错误用法
    Sword jemalloc使用小结
  • 原文地址:https://www.cnblogs.com/fuhaots2009/p/3468888.html
Copyright © 2020-2023  润新知