前页:设计模式总述
我们在编程的时候,常常遇见这种情况:大量相同的类进行初始化,需要用到大量的构造函数。最基本的例子:
while(count-- > 0){
String a = new String("asd");
}
这就是最简单的String类的构造函数。当我们频繁创建该对象时,会耗费资源且较耗时,因此,字这种情况下,java给出了一种方法,我们可以实现cloneable接口,从而生成大量类似对象。这就是原型模式。
public class ResembleType implements Cloneable{ //实现Cloneable接口
public ResembleType () { //本身类的构造函数
System.out.println("这里是原型");
}
@override
public Object clone()throws CloneNotSupportedException{ //具体实现克隆的方法
System.out.println("这里是复制原型");
return (ResembleType)super.clone();
}
}
public class ProtoType { //主函数调用
public static void main(String[] args) throws CloneNotSupportedException {
ResembleType resembleType = new ResembleType();
ResembleType resembleType2 = (ResembleType)resembleType.clone();
}
}
初次看这个模型,挺懵的。再来看看Cloneable源码:
/**
* A class implements the Cloneable
interface to
* indicate to the {@link java.lang.Object#clone()} method that it
* is legal for that method to make a
* field-for-field copy of instances of that class.
*
* Invoking Object's clone method on an instance that does not implement the
* Cloneable
interface results in the exception
* CloneNotSupportedException
being thrown.
*
* By convention, classes that implement this interface should override
* Object.clone (which is protected) with a public method.
* See {@link java.lang.Object#clone()} for details on overriding this
* method.
*
* Note that this interface does not contain the clone method.
* Therefore, it is not possible to clone an object merely by virtue of the
* fact that it implements this interface. Even if the clone method is invoked
* reflectively, there is no guarantee that it will succeed.
*
* @author unascribed
* @see java.lang.CloneNotSupportedException
* @see java.lang.Object#clone()
* @since JDK1.0
*/
public interface Cloneable {
}
这个Cloneable接口什么都没有写,也就是说不用实现它要求实现的函数。但是,我们需要重写方法:
protected native Object clone() throws CloneNotSupportedException;
在这里,Cloneable接口仅仅是个标记。 如果不重写clone方法,编译器抛错。
public class ResembleType implements Cloneable{
private String name;
private int age;
public ResembleType(String name, int age){
this.name = name;
this.age = age;
}
public void show(){
System.out.println(this.name + " " + this.age);
}
@Override
public Object clone()throws CloneNotSupportedException{
return (ResembleType) super.clone();
}
}
public class ProtoType {
public static void main(String[] args) throws CloneNotSupportedException {
ResembleType resembleType = new ResembleType("Jack", 11);
ResembleType resembleType2 = (ResembleType)resembleType.clone();
resembleType.show();
resembleType2.show();
}
}
我们逐步加难度,现在这个类里面有两个私有成员了。在调用show函数的时候,我们看结果,和我们想要的一样
这种方式和直接new一个构造函数有什么区别呢?
答案就是:这种方式不会调用类中的构造函数,因为clone方法的原理是从堆内存中以二进制流的方式进行拷贝,直接分配一块新内存。
我总是回避JVM的内容,因为一直没有时间去拜读《深入理解JAVA虚拟机》这本书,因此对JVM也一知半解。
但是这里涉及到一个深浅克隆的问题。这与C++的深浅拷贝有些类似:拷贝构造函数。这是之前C++语言的内容,可以看一下,语言总是相通的。
java中基本数据类型有:int,char,short,long,float,double
复合数据类型有:String,enum,数组,自定义类等
图在:深浅拷贝
因此,如果使用浅克隆,得到的结果可能不尽人意。因为它在改变值的时候会连被克隆的对象的值一起改变,那么怎么实现深克隆呢?
答案也很简单,重写clone方法。
public Object clone()throws CloneNotSupportedException{
ResembleType resembleType = (ResembleType)super.clone();
resembleType.setName(resembleType.getName());
return resembleType;
//return (ResembleType) super.clone();
}
//注意,若是自定义类,getName()要引用.clone()