前提:对于常规数据类型而言,可以分为值类型和引用类型,值类型为我们常说的”主类型”,”值类型”直接将内存存储在栈内,由系统自动释放资源的数据类型;引用类型是由类型的实际值引用(类似于指针)表示的数据类型,即一个在栈上的引用指向一个在堆上的实例的类型。
一.值的传递
当将应用类型和值类型作为参数进行传递时,会制作一个本地副本(引用类型我认为也是有一个副本,只不过是引用的副本),以下为2种情形:
1.值类型传递
public void f(int b);
因此值类型传值在方法体内对b的操作不会影响到a的值
2.引用类型传递
public void f(Object b)
因此引用类型传值在方法体内对b的操作会影响到a的值,但只能改变值,不能改变引用关系,如b=null,这时a并不等于null,这个操作只是将b指向空,a依旧指向a的实例。
二.对象的克隆
对象要具备克隆能力,必须实现Cloneable接口,这个接口不含任何方法,它只是一个标识,表明这个类型的对象具备克隆能力,在具备克隆能力之后,还得重写clone()方法,将之覆盖为public。对象的克隆分为“浅层次克隆”于”深层次克隆”。以下为普通对象和合成对象的测试。
1.普通对象的克隆
public class Test {
public static void main(String[] args) throws CloneNotSupportedException{
Student a=new Student("Lz");
Student b=a.clone();
b.name="Qy";
System.out.println(a.hashCode()+a.name);
System.out.println(b.hashCode()+b.name);
}
}
class Student implements Cloneable
{
String name;
Student(String name)
{
this.name=name;
}
@Override
public Student clone() throws CloneNotSupportedException {
Student o=null;
o=(Student) super.clone();
return o;
}
}
这是最简单的克隆情况,输出2个对象的名字和hashCode(),发现名字和hashCode()都是不一样,这是2个不同的对象。
2.合成对象的“浅层次”克隆
public class Test {
public static void main(String[] args) throws CloneNotSupportedException{
MyClass classOne=new MyClass();
MyClass classTwo=classOne.clone();
System.out.println(classOne.hashCode());
System.out.println(classTwo.hashCode());
classOne.a.name="QE";
System.out.println(classTwo.a.name);
System.out.println(classOne.a.hashCode());
System.out.println(classTwo.a.hashCode());
}
}
class MyClass implements Cloneable
{
Student a=new Student("Lz");
Student b=new Student("Qy");
@Override
public MyClass clone() throws CloneNotSupportedException {
MyClass o=null;
o=(MyClass) super.clone();
return o;
}
}
class Student implements Cloneable
{
String name;
Student(String name)
{
this.name=name;
}
@Override
public Student clone() throws CloneNotSupportedException {
Student o=null;
o=(Student) super.clone();
return o;
}
}
输出结果:
从结果中,可以发现classOne和classTwo是2个不同的对象,它们的hashCode()不同,改变classOne.a.name的值,classTwo.a.name的值也跟着改变,且它们的hashCode()相同,它们是同一个对象。这是为什么呢?这就是”浅层次复制”,即只复制了对象的表面,它的内部对象并没有改变。
3.合成对象的“深层次克隆”
将Myclass类的clone()方法改成下面这样:
@Override
public MyClass clone() throws CloneNotSupportedException {
MyClass o=null;
o=(MyClass) super.clone();
o.a=a.clone();
o.b=b.clone();
return o;
}
在clone()里面,手动调用内部对象的克隆方法,将表面对象的内部对象引用分别指向内部对象clone()方法返回的对象。