由clone()所引出的对protected的思考

一、阐述问题

我在用clone()进行对象的复制时,我们知道,调用的是Object类里面的clone()方法进行的,但是clone()是protected修饰的,而当我用已有的对protected的认识去代码时,发现事实并不是我认为的那样。

二、问题代码

1.这是父类(clones)的代码,位于test2包中

package test2;
public class clones {

	 protected void cloned() {
		   System.out.println("cloned");
	 }
}

2.这是子类(Student、teacher)的代码,位于test1包内

 package test1;
		import test2.clones;      //这里记得导入
		public class Student extends clones
		{
			private String name;
			private String age;
			public Student(String n,String a)
			{
				this.name=n;
				this.age=a;
			}
			public static void main(String[] args) 
			{
				Student s=new Student("lzc", "13");
	            s.cloned();   //访问成功
				teacher t=new teacher();
				t.cloned();  //访问失败
				
			}


		}
		class teacher extends clones{
			  public void c() {
				  
			  }
		}

以上的父类与子类位于不同的包内,两个子类(Student、teacher)位于同一个包中,我们在Student类里面去实例化两个子类对象并且尝试调用父类的protected修饰的cloned()方法。结果是Student的对象可以调用成功,而teacher的对象则调用失败。

三、原因分析

1、protected的访问规则是:同一个包中的所有类以及不同包中的子类可以访问。我们刚才的问题就是出在 “不同包中的子类可以访问” ;我们要注意了,这句话是有限制的,比如:我在Student类的方法里面,那我只能Student s=new Student(“lzc”,“13”); 这个对象s才能访问父类clones里面的cloned()。也就是你在哪个子类里面,你的实例化对象必须就是对应这个子类的,别的是不行的。

2、有一句话是专门来描述这种情况的:“ 对于protected的成员或方法,要分子类和超类是否在同一个包中。与基类不在同一个包中的子类,只能访问自身从基类继承而来的受保护成员,而不能访问基类实例本身的受保护成员 ” 。老实的讲,我看不懂这句话,很多博文里面都有这句话,他们也没有详细讲讲这句话啥意思,比如什么是 “基类实例本身的受保护成员 ” 。我觉得对这句话的理解可以是我前面第一点所理解的那样的。

四、使用clone()过程中,出现如上所描述的问题

1.我先把我是如何调用clone()的代码给出来,大家要耐住性子,我的代码的都是很短的,名字也都是取的特别容易短。

package test1;

public class Student{
    /*
     *  Student与teacher都是Object类的子类,它们与Object不在同一个包里面,当我们想在Student里面
     *  实例化对象,并且用这个对象调用父类的protected修饰的clone()时,只有Student类的对象调用成功了,
     *  这和我们在上面举出的那个例子不是一样的吗。    
     */
	public static void main(String[] args) 
	{
		teacher t=new teacher("lzc", "13");
		teacher copy=null;
		copy=(teacher)t.clone();  //这里报错了:The method clone() from the type Object is not visible。意思是teacher类的对象t不可访问Object类里面的clone()
		
		Student s=new Student();
		Student copy2=null;
		copy2=(Student) s.clone();  //编译成功
	}


}
class teacher {
	private String name;
    private String age;
	public teacher(String n,String a)
	{
		this.name=n;
		this.age=a;
	}
}

我们来回顾一下我在第二大点所举出的问题代码,以此来对比是否相同
1、首先是位于test2包的父类:clones

package test2;
public class clones {

	 protected void cloned() {
		   System.out.println("cloned");
	 }
}

2、然后是位于test1包的两个子类:Student、teacher

 package test1;
		import test2.clones;    //这里记得导入
		public class Student extends clones{
			private String name;
			private String age;
			public Student(String n,String a)
			{
				this.name=n;
				this.age=a;
			}
			public static void main(String[] args) 
			{
				Student s=new Student("lzc", "13");
	            s.cloned();   //访问成功
				teacher t=new teacher();
				t.cloned();  //访问失败
				
			}


		}
		class teacher extends clones{
			  public void c() {
				  
			  }
		}

3、大家仔细看看代码,然后再琢磨一下这句话:“ 对于protected修饰的成员或方法,要分子类和父类是否在同一个包中。与父类不在同一个包中的子类,只能访问自身从父类继承而来的受保护成员,而不能访问父类实例本身的受保护成员 ” 。其实这句话就是想说:要在所在类里面写与该类相同类型的实例化语句,获取所在类的对象。用这个对象去调用父类的protected方法才是可行的。

五、那么正确的clone()调用方法该是怎么样的?

我直接给出代码,在代码里面总结,请耐住性子,别着急,多看几遍。

package test1;
            /*
              *  clone的实现格式:
		      *  1.在A类中实现Cloneable接口并重写clone();
		      *  2.在B类中实例化A的类对象,并且对A类对象进行复制;
            */            
            class Body implements Cloneable
            {
				public Head head;
				public int a;
				public Body() {}
				public Body(Head head,int a) {this.head = head;this.a=a;}
		 
				@Override
				protected Object clone() throws CloneNotSupportedException {
				    //这里是深克隆,深克隆、浅克隆的区别后续文章会介绍。
					Body newbody=(Body)super.clone();  //执行了这句话(Body)super.clone()以后,body对象的副本在堆内存里面已经复制好一个份了,然后再把它的地址发布给外部引用变量
					newbody.head=(Head)head.clone();  //将引用变量的对象复制一份,返回新复制的对象的地址。
					 
					return super.clone();
				}		
	        }     
			class Student
			{
			    public void main(Strings[] args)				  
				{
				     Body b=new Body(new Head(),3);
					 Body copy=b.clone();  //调用Body里面重写的方法。
				}
			}

六、总结:

总结就是:看清楚你在哪个类里面,那么你实例化语句的对应类型也要是对应的这个类。比如在Student类里面,那么就是Student s=new Student(“lzc”,“18”); 还有看完这篇文章的同学,如果有疑问或者不同观点,大家评论区见哦~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值