首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >复制构造函数和防御性复制

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

Stack Overflow用户
提问于 2013-02-22 09:31:15
回答 5查看 16.6K关注 0票数 20

什么是复制构造函数

是否有人可以分享一个小例子,可以帮助理解与防御性复制原理

EN

回答 5

Stack Overflow用户

发布于 2013-02-22 09:45:02

下面是一个很好的例子:

代码语言:javascript
运行
复制
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);
  }

}

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

这是一个defensive副本,因为原始Point通过获取它的副本而受到保护,不受更改。

所以现在:

代码语言:javascript
运行
复制
// 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);

请注意,这并不一定是正确的创建对象的方式。然而,这是一种良好的创建对象的方法,可以确保您不会意外地拥有对同一个对象的两个引用。显然,如果这是你想要达到的目标,这才是一件好事。

票数 22
EN

Stack Overflow用户

发布于 2013-02-22 09:45:23

在C++中经常看到的复制构造函数是部分隐藏的、自动调用的操作所需的。

想到了java java.awt.PointRectangle;也是非常老的、易变的对象。

通过使用不可变对象(如StringBigDecimal ),只需分配对象引用即可。事实上,由于Java在C++之后的早期阶段,字符串中仍然存在一个愚蠢的复制构造函数。

代码语言:javascript
运行
复制
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<>(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);
    }
}

应请求

具有复制构造函数的泄漏类:

代码语言:javascript
运行
复制
public class Wrong {
    private final List<String> list;

    public Wrong(List<String> list) {
        this.list = list; // Error: now shares list object with caller.
    }

    /** Copy constructor */
    public Wrong(Wrong wrong) {
        this.list = wrong.list; // Error: now shares list object with caller.
    }

    public List<String> getList() {
        return list; // Error: now shares list object with caller.
    }

    public void clear() {
        list.clear();
    }
}

具有复制构造函数的更正类:

代码语言:javascript
运行
复制
public class Right {
    private final List<String> list;

    public Right(List<String> list) {
        this.list = new ArrayList<>(list);
    }

    public Right(Right right) {
        this.list = new ArrayList<>(right.list);
    }

    public List<String> getList() {
        return new ArrayList<>(list);
    }

    public List<String> getListForReading() {
        return Collections.unmodifiableList(list);
    }

    public void clear() {
        list.clear();
    }
}

使用测试代码:

代码语言:javascript
运行
复制
public static void main(String[] args) {
    List<String> list1 = new ArrayList<>();
    Collections.addAll(list1, "a", "b", "c", "d", "e");
    Wrong w1 = new Wrong(list1);
    list1.remove(0);
    System.out.printf("The first element of w1 is %s.%n", w1.getList().get(0)); // "b"
    Wrong w2 = new Wrong(w1);
    w2.clear();
    System.out.printf("Size of list1 %d, w1 %d, w2 %d.%n",
        list1.size(), w1.getList().size(), w2.getList().size());

    List<String> list2 = new ArrayList<>();
    Collections.addAll(list2, "a", "b", "c", "d", "e");
    Right r1 = new Right(list2);
    list2.remove(0);
    System.out.printf("The first element of r1 is %s.%n", r1.getList().get(0)); // "a"
    Right r2 = new Right(r1);
    r2.clear();
    System.out.printf("Size of list2 %d, r1 %d, r2 %d.%n",
        list2.size(), r1.getList().size(), r2.getList().size());
}

这意味着:

代码语言:javascript
运行
复制
The first element of w1 is b.
Size of list1 0, w1 0, w2 0.
The first element of r1 is a.
Size of list2 4, r1 5, r2 0.
票数 10
EN

Stack Overflow用户

发布于 2013-02-22 09:36:25

这是通过传递一个旧对象来创建一个新对象,复制它的值的地方。

代码语言:javascript
运行
复制
Color copiedColor = new Color(oldColor);

而不是:

代码语言:javascript
运行
复制
Color copiedColor = new Color(oldColor.getRed(),
                              oldColor.getGreen(), oldColor.getBlue());
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15020850

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档