Создает ли конструктор копирования мелкую копию? - PullRequest
0 голосов
/ 18 сентября 2018

Мой вопрос понятен.Конструктор копий делает глубокую копию?или мелкая копия?

Вот ситуация, с которой я столкнулся:

Я делаю приложение редактора узлов.У меня есть абстрактный класс Node.В этом у меня есть абстрактный метод Create ().Также я переопределил этот метод во всех подклассах следующим образом:

    public Node Create(){
    TestClass theTest = new TestClass();
    theTest.Name = "Test Node";
    theTest.Title = "Default Node";
    theTest.setSize(new Point2D.Float(250,200));
    System.out.print(theTest.getClass());
    return theTest;
}

Я думал, что это должно сделать глубокую копию.Так как это не сработало, я попробовал это также.

public Node Create(Point2D location) {
    TestClass theTest = null;
    try {
        theTest = this.getClass().newInstance();
    } catch (InstantiationException | IllegalAccessException e) {
        e.printStackTrace();
    }

    if (theTest != null) {
        theTest.Name = "The Node";
        theTest.Title = "Defaul Node";
        theTest.setSize((new Point2D.Float(250,200)));
        theTest.Location = location;
    }

    return theTest;
}

Затем все типы подклассов добавляются в список, и всплывающее меню создается с подклассами.Пользователь может щелкнуть по нему и добавить новый узел.Это код для добавления узла.Этот метод вызывается MouseEvent из JMenuItem.

private void addNode(Node node){
    Node newNode = node.Create(locationPersistence);
    nodes.add(newNode);
}

Но не повезло.Кажется, для создания мелкой копии вместо глубокой копии.Когда я добавляю первый узел, он выглядит нормально.Но при добавлении второго узла того же типа, первый узел оттуда исчезает и вновь появляется в новом местоположении.Означает ли это, что это делает мелкую копию.Если да, то как добиться глубокого копирования?

Ответы [ 3 ]

0 голосов
/ 18 сентября 2018

Конструктор копирования - это когда ваш класс содержит конструктор, который принимает экземпляр себя в качестве параметра. Параметр используется для создания нового экземпляра класса, который имеет те же значения для своих полей, что и класс экземпляра, предоставленный в качестве параметра.

Ваш класс Node должен иметь конструктор, подобный этому:

public class Node {
    public Node(Node n) {
       //copy all fields in Node n here
       //eg this.a = n.a
       //this.b = n.b etc
    }
}

Затем, когда вы наследуете от Node, вам нужно также вызвать этот родительский метод в конструкторе дочернего класса:

public class TestClass extends Node {
    public TestClass(TestClass t) {
        super(t);
        //copy any additional fields that is only present in TestClass here
    }
}

Теперь разница между мелкой и глубокой копией. Мелкая копия - это когда ссылка установлена ​​равной другой ссылке. Например:

Point2D a = new Point2D(50, 50);
Point2D b = a;

Когда вы изменяете значение одного из членов a, также влияет b. Причина в том, что и a, и b являются ссылкой на один и тот же объект.

a.x = 100;
System.out.println(b.x == 100); //prints true

Теперь глубокая копия - это если a и b ссылаются на свои собственные экземпляры. Это можно сделать следующим образом:

Point2D a = new Point2D(50, 50);
Point2D b = new Point2D();
b.x = a.x
b.y = a.y

Если я сейчас наберу:

a.x = 100

тогда b.x не изменится на это же значение, но сохранит предыдущее значение, которое изначально было сохранено в a, в данном случае 50.

System.out.println(b.x == 100); //prints false
System.out.println(b.x == 50); //prints true

Если вы хотите иметь глубокое копирование в своем конструкторе, то вам нужно убедиться, что все члены класса, которые являются ссылками на изменяемые классы, ссылаются на свои собственные экземпляры

0 голосов
/ 18 сентября 2018

Java избегает глубокого копирования.

Для неизменяемого класса String это не проблема, поскольку строки могут использоваться совместно.

Для старого изменяемого класса Java java awt Point2D.Float действительно естьпроблема.Замена его неизменным классом, вероятно, была бы лучше - чем глубокое копирование.Файл javafx.geometry.Point2D является неизменным.

Для изменяемых массивов существует проблема.Даже массив final может изменять свои элементы извне.Здесь совет будет использовать вместо этого коллекции.

private final List<Point2D> points = new ArrayList<>();

public List<Point2D> getPoints() {
    return Collections.unmodifiableList<>(points);
}

Используйте Java-соглашение о именах полей и методов, начинающихся с маленькой буквы.В этом отношении Java достаточно строг.

C / C ++ частично требует глубокого копирования для хранения объектов в локальном стеке.

Java несколько устранила необходимость в конструкторах копирования, но исторически не удавалась для String: String имеет бессмысленный конструктор копирования, вероятно, спровоцированный intern() и имеющий внутренний массив символов.

0 голосов
/ 18 сентября 2018

Во-первых, в Java нет такого понятия, как конструктор копирования по умолчанию.Существует интерфейс Cloneable и метод clone().Но этот метод по умолчанию сделает мелкое копирование.

Ваш код устанавливает ссылку на одинаковые Point2D ссылки на объекты в свойстве location для обоих объектов.Вам нужно создать новый экземпляр объекта Point2D и использовать его в новом объекте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...