呐,码农呢,还是要多看点源码,喏->....
clone() 方法不可见, Oh No!!!
protected关键字
如果要是问我:protected
这个关键字,该如何理解?
重点需要提及:
- java 限定访问范围的关键词
- 修饰成员属性,会怎么样?
- 修饰方法,会怎样?
- 能否修饰类?
- 他跟public, private,default有什么区别
- 巴拉拉拉啊啦啦 …..
嗯~, 注意,这不是讲解java基础面试题,以上我是不会给你回答的 (任性,没办法~)。只是想说,看到 protected
我可能会从这些方面回答,这其中,有趣的是,我们知道 protected
是受保护的含义,但是到我们实际遇到问题的时候,会短路一会,然后,会, 哦~, 原来是这样!!!
您不信? 那就看看下面的情况 ~
clone()
最近,在梳理java知识点,在梳理到clone() 方法的时候,信手拈来 写了一段代码, 目的很简单。demo1 是DemoObject类型的变量, 想把demo1 “复制”一份给 demo2
伪代码
DemoObject demo1 = new DemoObject(param1, param2, ...paramN)
DemoObject demo2 = demo1.clone()
看到这里,请亲爱的你 关闭当前页面,花2分钟在IDE中快速写下, 看是否会遇到问题。
参考代码
public class DemoObject {
int ver1;
int ver2;
int ver3;
int ver4;
String string1;
String string2;
String string3;
String string4;
DemoObject() {
}
DemoObject(int ver1, int ver2, int ver3, int ver4,
String string1, String string2, String string3, String string4) {
this.ver1 = ver1;
this.ver2 = ver2;
this.ver3 = ver3;
this.ver4 = ver4;
this.string1 = string1;
this.string2 = string2;
this.string3 = string3;
this.string4 = string4;
}
}
- 以上代码是有瑕疵的,知道的同学,给我留言, 毫不留情 指出我的瑕疵,鞭策我成长 (感觉我有受虐强迫妄想症 ~)
public class JavaDay04 {
JavaDay04() {
}
public static void main(String... args) {
DemoObject demo1 = new DemoObject(1, 2, 3, 4, "11", "22", "33", "44");
System.out.println(demo1);
DemoObject demo2 = demo1.clone() // 有问题~
}
你会发现,clone
方法显示不了, 再打 equal
却可以。 嗯,问题来了,这是怎么回事?
IDE 也会提示 clone() has protected access in java.lang.Object
不要问我,看源码~
protected native Object clone() throws CloneNotSupportedException;
这里要明确 2点: 参考 Java 访问权限控制:你真的了解 protected 关键字吗?
- (1)父类的protected成员 包内可见且对其子类可见;
- (2)对于子类父类不同包情形,在子类中,只能访问自身从基类继承而来protected成员,而不能访问基类实例本身的protected成员。
针对我们具体的问题,分析如下:
首先, DemoObject 继承自 Object, JavaDay04 继承自Object, DemoObject & JavaDay04 没有继承关系。 没有疑问! 按照 (1)说法,Object中的clone() 在DemoObject 以及JavaDay04中可以访问到, 没毛病 (不信? 自己手打验证下~)
其次,按照 (2)说法,可以知道
DemoObject demo2 = demo1.clone()
无法通过编译,因为上述代码的范围是在JavaDay04类中,要想让demo1.clone()
可见,需要在DemoObject中重写clone
方法。
DemoObject修改如下
public class DemoObject {
.......
////////// 新增///////////////
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
修改之后,在JavaDay04.java 中的调用 就可以访问 clone()
....
public static void main(String... args) {
DemoObject demo1 = new DemoObject(1, 2, 3, 4, "11", "22", "33", "44");
System.out.println(demo1);
try {
DemoObject demo2 = (DemoObject) demo1.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
但是运行 直接crash
aaa@qq.com2503dbd3
java.lang.CloneNotSupportedException: DemoObject
at java.lang.Object.clone(Native Method)
at DemoObject.clone(DemoObject.java:53)
at JavaDay04.main(JavaDay04.java:11)
来,还是来看源码。
Object.java 中 clone() 注释部分,有说明
* The method {@code clone} for class {@code Object} performs a
* specific cloning operation. First, if the class of this object does
* not implement the interface {@code Cloneable}, then a
* {@code CloneNotSupportedException} is thrown.
注意,其中关键字 Cloneable
,要想顺利使用clone() , 需要让DemoObject实现 Cloneable 接口, 所有,DemoObject再次 修改如下。
public class DemoObject implements Cloneable {
}
修改JavaDay04
// 省略 ...
try {
DemoObject demo2 = (DemoObject) demo1.clone();
System.out.println(demo2);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
打印结果为:
DemoObject@2503dbd3
DemoObject@4b67cf4d
小结
从clone() 方法,可以考察的点, 有如下几个:
1. protected
关键自的含义
2. clone() 该如何正确的使用
针对 1. 可以有如下的 示例图 给我们展示。
(图片来自: https://blog.csdn.net/justloveyou_/article/details/61672133)
至于 java clone() 默认是浅拷贝,还是深拷贝?本来是要继续解读一下的,但是发现有比我写的更好的文章,参考:
详解Java中的clone方法 – 原型模式
工具推荐
如果想看 Java 字节码同学,可以在Intellij 上安装一个ASM插件,如何安装,使用,你懂的。
祝 春安!
2018年03月31