重写 clone() 得到以下实现:
public class CloneExample { private int a; private int b; @Override public CloneExample clone() throws CloneNotSupportedException { return (CloneExample)super.clone(); } } CloneExample e1 = new CloneExample(); try { CloneExample e2 = e1.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } java.lang.CloneNotSupportedException: CloneExample以上抛出了 CloneNotSupportedException,这是因为 CloneExample 没有实现 Cloneable 接口。
应该注意的是,clone() 方法并不是 Cloneable 接口的方法,而是 Object 的一个 protected 方法。Cloneable 接口只是规定,如果一个类没有实现 Cloneable 接口又调用了 clone() 方法,就会抛出 CloneNotSupportedException。
public class CloneExample implements Cloneable { private int a; private int b; @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } } 浅拷贝拷贝对象和原始对象的引用类型引用同一个对象。
public class ShallowCloneExample implements Cloneable { private int[] arr; public ShallowCloneExample() { arr = new int[10]; for (int i = 0; i < arr.length; i++) { arr[i] = i; } } public void set(int index, int value) { arr[index] = value; } public int get(int index) { return arr[index]; } @Override protected ShallowCloneExample clone() throws CloneNotSupportedException { return (ShallowCloneExample) super.clone(); } } ShallowCloneExample e1 = new ShallowCloneExample(); ShallowCloneExample e2 = null; try { e2 = e1.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } e1.set(2, 222); System.out.println(e2.get(2)); // 222 深拷贝拷贝对象和原始对象的引用类型引用不同对象。
public class DeepCloneExample implements Cloneable { private int[] arr; public DeepCloneExample() { arr = new int[10]; for (int i = 0; i < arr.length; i++) { arr[i] = i; } } public void set(int index, int value) { arr[index] = value; } public int get(int index) { return arr[index]; } @Override protected DeepCloneExample clone() throws CloneNotSupportedException { DeepCloneExample result = (DeepCloneExample) super.clone(); result.arr = new int[arr.length]; for (int i = 0; i < arr.length; i++) { result.arr[i] = arr[i]; } return result; } } DeepCloneExample e1 = new DeepCloneExample(); DeepCloneExample e2 = null; try { e2 = e1.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } e1.set(2, 222); System.out.println(e2.get(2)); // 2 clone的替代方案使用 clone() 方法来拷贝一个对象即复杂又有风险,它会抛出异常,并且还需要类型转换。Effective Java 书上讲到,最好不要去使用 clone(),可以使用拷贝构造函数或者拷贝工厂来拷贝一个对象。
public class CloneConstructorExample { private int[] arr; public CloneConstructorExample() { arr = new int[10]; for (int i = 0; i < arr.length; i++) { arr[i] = i; } } public CloneConstructorExample(CloneConstructorExample original) { arr = new int[original.arr.length]; for (int i = 0; i < original.arr.length; i++) { arr[i] = original.arr[i]; } } public void set(int index, int value) { arr[index] = value; } public int get(int index) { return arr[index]; } } CloneConstructorExample e1 = new CloneConstructorExample(); CloneConstructorExample e2 = new CloneConstructorExample(e1); e1.set(2, 222); System.out.println(e2.get(2)); // 2 关键字 final 数据声明数据为常量,可以是编译时常量,也可以是在运行时被初始化后不能被改变的常量。
对于基本类型,final 使数值不变;
对于引用类型,final 使引用不变,也就不能引用其它对象,但是被引用的对象本身是可以修改的。
final int x = 1; // x = 2; // cannot assign value to final variable 'x' final A y = new A(); y.a = 1; 方法声明方法不能被子类重写。
private 方法隐式地被指定为 final,如果在子类中定义的方法和基类中的一个 private 方法签名相同,此时子类的方法不是重写基类方法,而是在子类中定义了一个新的方法。
类声明类不允许被继承。
static 静态变量静态变量:又称为类变量,也就是说这个变量属于类的,类所有的实例都共享静态变量,可以直接通过类名来访问它。静态变量在内存中只存在一份。
实例变量:每创建一个实例就会产生一个实例变量,它与该实例同生共死。
public class A { private int x; // 实例变量 private static int y; // 静态变量 public static void main(String[] args) { // int x = A.x; // Non-static field 'x' cannot be referenced from a static context A a = new A(); int x = a.x; int y = A.y; } } 静态方法