三、常见错误3#:不必要的克隆

  我们现在知道了get方法应该返回内部数据对象的拷贝,而不是引用。但是,事情没有:

/*** Example class.The value should never * be negative.*/ public class Example{
private Integer i = new Integer (0);
public Example (){
}
/*** Set x. x must be nonnegative* or an exception will be thrown*/
public synchronized void setValues (int x) throws IllegalArgumentException{ if (x < 0)
throw new IllegalArgumentException();
i = new Integer (x);
}
public synchronized Integer getValue(){
// We can’t clone Integers so we makea copy this way. return new Integer (i.intValue());
}
}

  这段代码是安全的,但是象在错误1#那样,又作了多余的工作。Integer对象,象String对象那样,一旦被创建是不可变的。因此,返回内部Integer对象,而不是它的拷贝,也是安全的。

  方法getValue()应该被写为:

public synchronized Integer getValue(){ // ’i’ is immutable, so it is safe to return it instead of a copy. return i; }

  Java程序比C++程序包含更多的不可变对象。JDK 所提供的若干不可变类包括:

  Boolean
  Byte
  Character
  Class
  Double
  Float
  Integer
  Long
  Short
  String

  大部分的Exception的子类

  四、常见错误4#:自编代码来拷贝数组

  Java允许你克隆数组,但是开发者通常会错误地编写如下的代码,问题在于如下的循环用三行做的事情,如果采用Object的clone方法用一行可以完成:

public class Example{ private int[] copy;
/*** Save a copy of ’data’. ’data’ cannot be null.*/ public void saveCopy (int[] data){
copy = new int[data.length];
for (int i = 0; i < copy.length;
++i) copy[i] = data[i];
}
}

  这段代码是正确的,但却不必要地复杂。saveCopy()的一个更好的实现是:

void saveCopy (int[] data){ try{ copy = (int[])data.clone(); }catch (CloneNotSupportedException e){ // Can’t get here. } }

  如果你经常克隆数组,编写如下的一个工具方法会是个好主意:

static int[] cloneArray (int[] data){
try{
return(int[])data.clone();
}
catch(CloneNotSupportedException e){
// Can’t get here.
}
}

  这样的话,我们的saveCopy看起来更简洁了:

void saveCopy (int[] data){
copy = cloneArray ( data);
}