这是一个native方法,说一下他的使用方法以及和new的区别
研究的原因:
主要是对于这种底层实现的方式产生了一定的兴趣。在Android底层的native方法执行是效率较高的。所以想探寻一下和普通new对象到底的有什么区别。顺带一提,这个方法是在glide的源码中发现的,阅读源码真的对学习有很大帮助。
1. 实现方法
首先所有的类都是默认继承Object我想这个没有异议。然后在Object.java中,有这么一个方法:
protected Object clone() throws CloneNotSupportedException {
if (!(this instanceof Cloneable)) {
throw new CloneNotSupportedException("Class " + getClass().getName() +
" doesn't implement Cloneable");
}
return internalClone();
}
这是一个protected
方法,点进去看一下Cloneable,发现是一个空接口。
public interface Cloneable {
}
也就是说,如果当前类需要使用这个方法,就必须继承这个接口,不然会抛出异常。
接下来往下看internalClone()
,这就是native方法了。
/*
* Native helper method for cloning.
*/
@FastNative
private native Object internalClone();
也就是说我们探寻这个方法的本质只能通过注释以及实际操作去了解了。
写个Bean类试一下
public class Rat implements Cloneable{
private int count;
private String obj;
@NonNull
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public Rat(){
go();
}
public Rat(int count,String obj){
this.count = count;
this.obj = obj;
go(count,obj);
}
private void go(int count,String obj) {
Log.i("Rat","hello,你("+obj +")走了有参构造,小白鼠一共"+count+"只");
}
private void go() {
Log.i("Rat","hello,你走了无参构造");
}
public void setCount(int count){
this.count = count;
}
public int getCount(){
return count;
}
public String getObj() {
return obj;
}
public void setObj(String obj) {
this.obj = obj;
}
@Override
public String toString() {
return "Rat{" +
"count=" + count +
", obj='" + obj + '\'' +
'}';
}
}
尝试调用:
var rat = Rat(10,"第一次new")
var rat1 = Rat()
var cRat = rat.clone() as Rat
var cRat1 = rat1.clone() as Rat
Log.i("rat",rat.count.toString())
Log.i("rat1",rat1.count.toString())
Log.i("cRat",cRat.count.toString())
Log.i("cRat1",cRat1.count.toString())
rat.count = 20
rat.obj="修改了一下"
Log.i("rat",rat.toString())
Log.i("cRat",cRat.toString())
cRat.count = 15
cRat.obj = "把clone对象修改下"
Log.i("rat",rat.toString())
Log.i("cRat",cRat.toString())
看下日志结果:
10:33:12.025 2015-2015/com.yirong.myapplication I/Rat: hello,你(第一次new)走了有参构造,小白鼠一共10只
10:33:12.025 2015-2015/com.yirong.myapplication I/Rat: hello,你走了无参构造
10:33:12.025 2015-2015/com.yirong.myapplication I/rat: 10
10:33:12.025 2015-2015/com.yirong.myapplication I/rat1: 0
10:33:12.025 2015-2015/com.yirong.myapplication I/cRat: 10
10:33:12.025 2015-2015/com.yirong.myapplication I/cRat1: 0
10:33:12.025 2015-2015/com.yirong.myapplication I/rat: Rat{count=20, obj='修改了一下'}
10:33:12.025 2015-2015/com.yirong.myapplication I/cRat: Rat{count=10, obj='第一次new'}
10:33:12.025 2015-2015/com.yirong.myapplication I/rat: Rat{count=20, obj='修改了一下'}
10:33:12.025 2015-2015/com.yirong.myapplication I/cRat: Rat{count=15, obj='把clone对象修改下'}
从日志中,我们可以看出几点:
- clone()方法并不走构造函数
- clone后的对象和原对象参数一致
- clone后的对象是独立的,原对象的修改并不能影响clone对象,反之同理。
在Glide4.0中新增了RequestOptions,把关于占位图以及一系列缓存配置移到了这个类中,使用了clone。
requestOptions = requestOptions.clone().optionalCenterCrop();
这样在频繁调用不同配置时不需要new新的对象,学习了,记一下笔记。
看官觉得有错误或者补充的可以帮忙修正下,感激不尽。
网友评论