复制构造函数和防御性复制

use*_*103 14 java defensive-programming

什么是复制构造函数

有人可以分享一个小例子,有助于理解防御性复制原则吗?

Old*_*eon 16

这是一个很好的例子:

class Point {
  final int x;
  final int y;

  Point(int x, int y) {
    this.x = x;
    this.y = y;
  }

  Point(Point p) {
    this(p.x, p.y);
  }

}
Run Code Online (Sandbox Code Playgroud)

注意构造函数如何Point(Point p)获取Point并复制它 - 这是一个copy constructor.

这是一份defensive副本,因为通过复制原件Point可以保护原件免受更改.

所以现在:

// A simple point.
Point p1 = new Point(3,42);
// A new point at the same place as p1 but a completely different object.
Point p2 = new Point(p1);
Run Code Online (Sandbox Code Playgroud)

请注意,这不一定是创建对象的正确方法.但是,这是一种创建对象的方法,可以确保您不会偶然对同一对象进行两次引用.显然,如果这是你想要达到的目标,这只是一件好事.


Joo*_*gen 7

复制构造函数经常在C++中看到,部分隐藏,自动调用的操作需要它们.

java java.awt.PointRectangle浮现在脑海中; 也是非常古老,可变的物体.

通过使用不可变对象,String或者BigDecimal,只需分配对象引用即可.事实上,由于Java之后的Java早期阶段,String中仍然存在一个愚蠢的复制构造函数:

public class Recipe {
    List<Ingredient> ingredients;

    public Recipe() {
        ingredients = new ArrayList<Ingredient>();
    }

    /** Copy constructor */
    public Recipe(Recipe other) {
        // Not sharing: ingredients = other.ingredients;
        ingredients = new ArrayList<Ingredient>();
        ingredients.addAll(other.ingredients);
    }

    public List<Ingredient> getIngredients() {
        // Defensive copy, so others cannot change this instance.
        return new ArrayList<Ingredient>(ingredients);
        // Often could do:
        // return Collections.immutableList(ingredients);
    }
}
Run Code Online (Sandbox Code Playgroud)


Mor*_*hai 1

您可以在此处通过传递旧对象并复制其值来创建新对象。

Color copiedColor = new Color(oldColor);
Run Code Online (Sandbox Code Playgroud)

代替 :

Color copiedColor = new Color(oldColor.getRed(),
                              oldColor.getGreen(), oldColor.getBlue());
Run Code Online (Sandbox Code Playgroud)