主要内容

  1. 深拷贝与浅拷贝
  2. 算法:把数组排成最小的数

深拷贝与浅拷贝

浅拷贝

浅拷贝对于基本类型的属性会直接进行值传递,也就是对于基本类型的属性会复制一份给新的对象。而对于引用类型的属性,浅拷贝会进行引用的传递。因为传递的是引用,因此复制后的对象的此属性和原对象的属性指向同一个对象
一段代码来证明:

1
2
3
4
//引用对象
public class RefObj {
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class MyObj  implements Cloneable{
//一定要实现标记接口Colneable否则会报CloneNotSupportedException异常
private int val; //基本类型的属性
private RefObj ref; //引用类型的属性
public MyObj(int val,RefObj ref){
this.val=val;
this.ref=ref;
}


public static void main(String[] args) throws CloneNotSupportedException {
final MyObj A = new MyObj(1, new RefObj());
final MyObj clone = (MyObj)A.clone();
System.out.println(A == clone); //输出false
System.out.println(A.ref == clone.ref); //输出true
}
}

深拷贝

深拷贝对于基本类型的变量的处理方法和浅拷贝一致,都是复制一份给新的对象。而对于引用类型,深拷贝会复制引用的对象,然后让克隆产生的新对象中的对应属性指向这个复制的引用对象。

那么如何实现深拷贝呢?
常见的有两种方法,一种是重新Cloneable接口中的clone()方法

  1. 方案一:
1
2
3
4
5
6
7
8
9
public class RefObj  implements  Cloneable{

@Override
public Object clone() throws CloneNotSupportedException {
//这个地方进行重写主要为了是改变clone()的访问级别
return super.clone();
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class MyObj  implements  Cloneable{
public int val;
public RefObj ref;
public MyObj(int val,RefObj ref){
this.val=val;
this.ref=ref;
}
@Override
protected Object clone() throws CloneNotSupportedException {
MyObj clone = (MyObj)super.clone();
//让新对象的ref指向一个复制的新的对象
clone.ref= (RefObj) clone.ref.clone();
return clone;
}


public static void main(String[] args) throws CloneNotSupportedException {
final MyObj A = new MyObj(1, new RefObj());
final MyObj clone = (MyObj)A.clone();
System.out.println(A == clone); //输出false
System.out.println(A.ref == clone.ref); //输出false
}

}

  1. 方案二,通过序列化来实现深拷贝
1
2
3
4
public class RefObj  implements Serializable {

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class MyObj  implements Serializable {
public int val;
public RefObj ref;
public MyObj(int val,RefObj ref){
this.val=val;
this.ref=ref;
}

public static void main(String[] args) throws IOException, ClassNotFoundException {

final MyObj obj = new MyObj(1, new RefObj());
ByteArrayOutputStream baos=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(baos);
oos.writeObject(obj);

oos.flush();

ObjectInputStream ois=new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
final MyObj cloneObj = (MyObj) ois.readObject();

System.out.println(obj == cloneObj); //输出flase
System.out.println(obj.ref == cloneObj.ref);//输出flase


}

必须实现标记接口Serializable

算法:把数组排成最小的数

题目:
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。

思路:
任意两个拼接后进行比较,比如:s1+s2,和s2+s1,如果s1+s2大,那说明s2应该放前面,所以按这个规则,s2就应该排在s1前面.按照这个比较的方法,按照冒泡排序的思路,对数组进行排序即可,最后拼接。

解法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.util.ArrayList;

public class Solution {
public String PrintMinNumber(int [] numbers) {
for(int i=0;i<numbers.length;i++){
for(int j=0;j<numbers.length-i-1;j++){
long a=Long.valueOf(numbers[j]+""+numbers[j+1]);
long b=Long.valueOf(numbers[j+1]+""+numbers[j]);
if(b<a){
int tmp=numbers[j];
numbers[j]=numbers[j+1];
numbers[j+1]=tmp;
}
}
}
StringBuilder sb=new StringBuilder();
for (int i=0;i<numbers.length;i++){
sb.append(numbers[i]);
}
return sb.toString();
}
}