Страницы

Поиск по вопросам

Показаны сообщения с ярлыком клонирование. Показать все сообщения
Показаны сообщения с ярлыком клонирование. Показать все сообщения

четверг, 2 апреля 2020 г.

Почему нам доступна возможность вызвать MemberwiseClone во время процесса клонирования?

#c_sharp #клонирование

                    
Читая документацию по C# про метод MemberwiseClone() наткнулся на такой пример :

using System;

class MyBaseClass {
   public static string CompanyName = "My Company";
   public int age;
   public string name;
}

class MyDerivedClass: MyBaseClass {

   static void Main() {

   // Creates an instance of MyDerivedClass and assign values to its fields.
   MyDerivedClass m1 = new MyDerivedClass();
   m1.age = 42;
   m1.name = "Sam";

   // Performs a shallow copy of m1 and assign it to m2.
   MyDerivedClass m2 = (MyDerivedClass) m1.MemberwiseClone();
   }
}


У меня возник вопрос касательной вот этой строчки :

MyDerivedClass m2 = (MyDerivedClass) m1.MemberwiseClone();


Какое право мы имеем вызывать метод на объекте если в его сигнатуре прописан модификатор
доступа protected ?
    


Ответы

Ответ 1



Потому, что MemberwiseClone является методом класса Objeсt от которого наследуется MyDerivedClass, внутри которого и происходит вызов (Main тоже метод MyDerivedClass). Другими словами, внутри MyDerivedClass происходит вызов собственного protected-метода. Если бы MemberwiseClone вызывался у стороннего класса не связанного отношением наследования с вызывающим, то была бы ошибка на этапе компиляции: using System; class Another { } class MyDerivedClass { static void Main() { Another m1 = new Another(); Another m2 = (Another) m1.MemberwiseClone(); // Error } }

среда, 4 марта 2020 г.

Клонирование объектов Java

#java #ооп #классы #объекты #клонирование


В классе main есть: 
 1) класс сlass1 в котором есть двумерный массив и еще несколько переменных 
 2) функция func(class1 cl) которая принимает объект класса но возвращает другой
тип данных (float), при этом внутри тела функции проводятся манипуляции с двумерным
массивом класса что бы получить ответ

Так вот, проблема в том, что если я создам экземпляр класса, вызову функцию и передам
его туда, то после этого исходный массив объекта меняется (Что мне естественно не нужно) 
Я нашел решение в виде метода clone(), но хеш-код объектов то стал другим, а вот
хеш-код полей внутри клона объекта тот же, и соответственно при изменении массива одного
объекта изменяется массив другого 

Подскажите пожалуйста как решить эту проблему?
    


Ответы

Ответ 1



Сделайте class1 сериализуемым (добавьте implements Serializable в его определение). Сохраняем объекта класса в поток байтов: ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream ous = new ObjectOutputStream(baos); ous.writeObject(new class1()); ous.close(); теперь в func можно передать (class1)new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())).readObject() Таким образом объект класса сохраняется в поток из которого восстанавливаться независимый клон.

Ответ 2



Чтобы метод clone клонировал поля объекта, его нужно переопределить в самом классе. По умолчанию он оперирует только примитивными типами и указателями Но Вам нужно просто скопировать массив. Для этого есть метод Arrays.copyOf() или банально вызвать clone для массива Вот тут описаны разные методы получения копии массива https://stackoverflow.com/a/36513254/5376639

вторник, 31 декабря 2019 г.

Как в Linux клонировать диск в диск другого размера

#linux #hdd #диск #ssd #клонирование


Имеем Linux - Fedora 22,
HDD - на котором установлена система, 
требуется переехать на SDD который в два раза меньшего размера, но данных на HDD
мало, поэтому влезут.
Оба диска подключены к компьютеру.
Вопрос: как клонировать диск? Желательно средствами GNU Linux.

Уточнения:
1. CD/DVD - нет.
2. gparted - не работает с активным системным разделом.
3. Куда tar архив размещать? в /dev/null ? два диска всего.
4. Диски разного размера!  
    


Ответы

Ответ 1



Все можно сделать, главное аккуратно. Нужны следующие вещи: livecd диск или лучше флешка. Можно другого совместимого дистрибутива, к примеру ubuntu. оба диска должны быть подключены к компу. Процедура переноса. загрузится с live открыть gparted или любую другую любимую утилиту для разбивки диска. разбить ssd как нужно (home, root, swap и дальше по предпочтениям), отформатировать монтируем новые диски и старые. Рекомендую сделать в /mount папку old (для старого диска) и new (для нового). копируем данные. Так как это линукс, то можно с помощью cp, главное сохранить права. К примеру home cp -a /mount/old/home/ /mount/new/home. аналогично копируется корень. Но тут есть особеность - не все нужно копировать. к примеру, папку tmp не нужно (хотя ничего плохого не будет). Если в папка /mount/old/proc и /mount/old/sys что то будет внутри - это копировать не нужно (содержимое этих папок система создает сама). не забываем о boot разделе. если имена устройств поменялись (к примеру, home это был /dev/sda*1*, а стал /dev/sdb*4* - тут важна цифра, а не буква), то открываем файл /mount/new/etc/fstab и правим по феншую. осталось последнее - перенести загрузочную запись. Вначале копируем старый dd if=/dev/sdX of=/path/to/mbr_file.img bs=512 count=1, а потом переносим на новый. Так как мы не хотим потереть таблицу разделов, то нужно не все скопировать. dd if=/path/to/mbr_file.img of=/dev/sdX bs=446 count=1. Все, можно выключать, поставить диски по местам, поправить в биосе загрузочное устройство и пробовать. Что делать, если ничего не завелось? Старый диск скорее всего не поврежден. Так что им можно будет загрузиться. Плюс есть флешка. Можно восстановить. Но если честно, то я переносил немного по другому. Все как выше, разбил диск, скопировал home раздел, потом вытянул старый диск, и загрузился с флешки. И начал установку как обычно. В процессе установки главное не отформатировать home раздел (хотя потом все равно можно скопировать). Так как home раздел есть, то сохранятся все настройки программ. Потом только возможно нужно будет доустановить недостающие программы.

Ответ 2



Очень рекомендую присмотреться к проекту Clonezilla. Умеет копировать как линуксовые, так и виндовые разделы. Грузится с флэшки, болванки, сети, умеет работать в режиме сервера и раздавать образ через мультикаст. Запускается в режиме мастера, на русский переведено подавляющее большинство диалогов. Да, может понадобиться тем же gparted live ужать разделы до размеров влезающих на ssd, но остальные dd и cp -r там не нужны. Есть режим копирования с железки на железку, можно сначала в образ, а потом из образа.

среда, 18 декабря 2019 г.

Как применить метод clone() класса Object?

#java #объекты #клонирование


Код, написанный мной для тренировки: 

class Korobka {

    public double width, depth, height; //Объявление переменных
    public static int id = 4;

    Korobka(double w, double d, double h) {
        width = w;
        depth = d;
        height = h;
    }

    double volume() {
        return width * depth * height;
    }

    void measurement() {
        System.out.println("Длина коробки " + width);
        System.out.println("Ширина коробки " + depth);
        System.out.println("Высота коробки " + height);
        System.out.println("Объем коробки " + volume());
    }

    public static void main(String[] args) {
        Korobka k1 = new Korobka(4.5, 3.6, 3.7);
        Korobka k2 = new Korobka(4, 5, 6);
        k1.measurement();
        k2.measurement();
        int ID = Korobka.id;
        System.out.println(ID);
    }
}


Вздумалось мне метод clone() из класса Object применить.

Вопросы: 


Могу ли я применить этот метод, к примеру, к коробке k1 (для клонирования)?
Если да, то как это сделать?

    


Ответы

Ответ 1



В дополнение к предыдущим ответам хочу отметить, что лучше реализовать clone() вот так: class Korobka implements Cloneable { @Override public Korobka clone() { try { return (Korobka)super.clone(); } catch( CloneNotSupportedException ex ) { throw new InternalError(); } } //всё остальное } Так как вы интерфейс Cloneable указали, CloneNotSupportedException никогда случиться не должен, и пользователи вашего класса не должны мучаться с ним, оборачивая вызовы в try-catch. Кроме того вы можете быть уверены, что возвращаемый объект имеет тип Korobka и привести тип сами. Тогда пользователи смогут просто писать: Korobka copy = k1.clone(); Вообще у клонирования много проблем и оно не всегда хорошо (хотя бывают случаи, когда очень удобно). Альтернативой клонированию служит конструктор копирования: class Korobka { Korobka(double w, double d, double h) { width = w; depth = d; height = h; } Korobka(Korobka other) { this(other.width, other.depth, other.height); } } Пользоваться тогда немного по-другому: Korobka copy = new Korobka(k1);

Ответ 2



Да сможете. В java объекты передаются по ссылкам. Т.е. следующий код Object o1 = new Object(); Object o2 = o1; создаёт один объект, на который указывают две ссылки. Очень часто это бывает не удобно - изменяем объект о1 изменяется объект о2. А, к примеру, нужно было в объект о2 просто скопировать значения из о1, но никак не связывать их. Для этих целей был введён интерфейс Cloneable. В своём клаccе вам нужно реализовать его: class Korobka implements Cloneable { @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } //всё остальное }

Ответ 3



Для начала нужно, чтобы ваш класс Korobka имплементил маркерный интерфейс Cloneable. Далее, вам надо переопределить метод clone() и сделать его публичным. Тогда вы сможете где угодно в своем коде клонировать коробки. P.S. Прежде чем переопределять метод, почитайте про глубокое копирование объектов в Java. Хотя оно тут не пригодится, но всё равно почитайте.

вторник, 21 мая 2019 г.

Клонирование объектов Java

В классе main есть: 1) класс сlass1 в котором есть двумерный массив и еще несколько переменных 2) функция func(class1 cl) которая принимает объект класса но возвращает другой тип данных (float), при этом внутри тела функции проводятся манипуляции с двумерным массивом класса что бы получить ответ
Так вот, проблема в том, что если я создам экземпляр класса, вызову функцию и передам его туда, то после этого исходный массив объекта меняется (Что мне естественно не нужно) Я нашел решение в виде метода clone(), но хеш-код объектов то стал другим, а вот хеш-код полей внутри клона объекта тот же, и соответственно при изменении массива одного объекта изменяется массив другого
Подскажите пожалуйста как решить эту проблему?


Ответ

Сделайте class1 сериализуемым (добавьте implements Serializable в его определение).
Сохраняем объекта класса в поток байтов: ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream ous = new ObjectOutputStream(baos); ous.writeObject(new class1()); ous.close();
теперь в func можно передать (class1)new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())).readObject()
Таким образом объект класса сохраняется в поток из которого восстанавливаться независимый клон.

пятница, 12 апреля 2019 г.

Как в Linux клонировать диск в диск другого размера

Имеем Linux - Fedora 22, HDD - на котором установлена система, требуется переехать на SDD который в два раза меньшего размера, но данных на HDD мало, поэтому влезут. Оба диска подключены к компьютеру. Вопрос: как клонировать диск? Желательно средствами GNU Linux.
Уточнения: 1. CD/DVD - нет. 2. gparted - не работает с активным системным разделом. 3. Куда tar архив размещать? в /dev/null ? два диска всего. 4. Диски разного размера!


Ответ

Все можно сделать, главное аккуратно. Нужны следующие вещи:
livecd диск или лучше флешка. Можно другого совместимого дистрибутива, к примеру ubuntu. оба диска должны быть подключены к компу.
Процедура переноса.
загрузится с live открыть gparted или любую другую любимую утилиту для разбивки диска. разбить ssd как нужно (home, root, swap и дальше по предпочтениям), отформатировать монтируем новые диски и старые. Рекомендую сделать в /mount папку old (для старого диска) и new (для нового). копируем данные. Так как это линукс, то можно с помощью cp, главное сохранить права. К примеру home cp -a /mount/old/home/ /mount/new/home аналогично копируется корень. Но тут есть особеность - не все нужно копировать. к примеру, папку tmp не нужно (хотя ничего плохого не будет). Если в папка /mount/old/proc и /mount/old/sys что то будет внутри - это копировать не нужно (содержимое этих папок система создает сама). не забываем о boot разделе. если имена устройств поменялись (к примеру, home это был /dev/sda*1*, а стал /dev/sdb*4* - тут важна цифра, а не буква), то открываем файл /mount/new/etc/fstab и правим по феншую. осталось последнее - перенести загрузочную запись. Вначале копируем старый dd if=/dev/sdX of=/path/to/mbr_file.img bs=512 count=1, а потом переносим на новый. Так как мы не хотим потереть таблицу разделов, то нужно не все скопировать. dd if=/path/to/mbr_file.img of=/dev/sdX bs=446 count=1
Все, можно выключать, поставить диски по местам, поправить в биосе загрузочное устройство и пробовать.
Что делать, если ничего не завелось?
Старый диск скорее всего не поврежден. Так что им можно будет загрузиться. Плюс есть флешка. Можно восстановить.
Но если честно, то я переносил немного по другому. Все как выше, разбил диск, скопировал home раздел, потом вытянул старый диск, и загрузился с флешки. И начал установку как обычно. В процессе установки главное не отформатировать home раздел (хотя потом все равно можно скопировать). Так как home раздел есть, то сохранятся все настройки программ. Потом только возможно нужно будет доустановить недостающие программы.