By comparing with C + + program, the object copy of JAVA is made clear

catalog

1, Background

In JAVA programming, objects are generally created through new, and newly created objects are usually in the initial state. However, when some properties of the object change, and an object copy is required to save the "state" of the current object, the object copy function is needed to encapsulate the rapid cloning between objects.

2, The implementation of JAVA object copy

2.1 light copy
  • The copied class needs to implement the Clonenable interface;
  • Override clone() method, call super.clone() method to get the required copy object;
  • Shallow copy pair basic types (Boolean, char, byte, short, float, double.long )It can complete its own copy, but only copy the reference address for the reference type.
    --Let's use an example to verify:
/**
 * Single card
 *
 * @author zhuhuix
 * @date 2020-06-10
 */
public class Card implements Comparable, Serializable,Cloneable {

    // Decor
    private String color = "";
    //number
    private String number = "";

    public Card() {
    }

    public Card(String color, String number) {
        this.color = color;
        this.number = number;
    }

    public String getColor() {
        return this.color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public String getNumber() {
        return this.number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    @Override
    public String toString() {
        return this.color + this.number;
    }

    @Override
    public int compareTo(Object o) {
        if (o instanceof Card) {
            int thisColorIndex = Constant.COLORS.indexOf(this.getColor());
            int anotherColorIndex = Constant.COLORS.indexOf(((Card) o).getColor());
            int thisNumberIndex = Constant.NUMBERS.indexOf(this.getNumber());
            int anotherNumberIndex = Constant.NUMBERS.indexOf(((Card) o).getNumber());

            // Comparison between big Wang and small Wang: big wang is bigger than small Wang
            if ("JOKER".equals(this.color) && "JOKER".equals(((Card) o).getColor())) {
                    return thisColorIndex > anotherColorIndex ? 1 : -1;
            }

            // Comparison between big and small king and digital card: big and small king are greater than digital card
            if ("JOKER".equals(this.color) && !"JOKER".equals(((Card) o).getColor())) {
                return 1;
            }
            if (!"JOKER".equals(this.color) && "JOKER".equals(((Card) o).getColor())) {
                return -1;
            }

            // The number cards are compared with each other: if the number is not equal, the face is large; if the number is equal, the face is large
            if (thisNumberIndex == anotherNumberIndex) {
                return thisColorIndex > anotherColorIndex ? 1 : -1;
            } else {
                return thisNumberIndex > anotherNumberIndex ? 1 : -1;
            }

        } else {
            return -1;
        }
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
/**
 * Poker constant definition
 *
 * @author zhuhuix
 * @date 2020-06-10
 */
public class Constant {

    // Card decors: spades, hearts, clubs, diamonds
    final static List<String> COLORS = new ArrayList<>(
            Arrays.asList(new String[]{"♢", "♣", "♡", "♠"}));
    // Card numbers
    final static List<String> NUMBERS = new ArrayList<>(
            Arrays.asList(new String[]{"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"}));
    // Wang and Wang
    final static List<String> JOKER = new ArrayList<>(
            Arrays.asList(new String[]{"Xiao Wang","king"}));
}

/**
 * Deck of cards
 *
 * @author zhuhuix
 * @date 2020-06-10
 */
public class Poker implements Cloneable, Serializable {

    private List<Card> cards;

    public Poker() {
        List<Card> cardList = new ArrayList<>();
        // Generate 52 playing cards according to the combination of decors and numbers
        for (int i = 0; i < Constant.COLORS.size(); i++) {
            for (int j = 0; j < Constant.NUMBERS.size(); j++) {
                cardList.add(new Card(Constant.COLORS.get(i), Constant.NUMBERS.get(j)));
            }
        }
        // Generate size King
        for (int i = 0; i < Constant.JOKER.size(); i++) {
            cardList.add(new Card("JOKER", Constant.JOKER.get(i)));
        }

        this.cards = cardList;
    }

   
    // Take the king from the whole deck of playing cards
    public void removeJoker() {
        Iterator<Card> iterator = this.cards.iterator();
        while (iterator.hasNext()) {
            Card cardJoker = iterator.next();
            if (cardJoker.getColor() == "JOKER") {
                iterator.remove();
            }
        }
    }

    public List<Card> getCards() {
        return cards;
    }

    public void setCards(List<Card> cards) {
        this.cards = cards;
    }

    public Integer getCardCount() {
        return this.cards.size();
    }

    @Override
    public String toString() {
        StringBuilder poker = new StringBuilder("[");
        Iterator<Card> iterator = this.cards.iterator();
        while (iterator.hasNext()) {
            poker.append(iterator.next().toString() + ",");
        }
        poker.setCharAt(poker.length() - 1, ']');
        return poker.toString();
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

/**
 * Test procedure
 *
 * @author zhuhuix
 * @date 2020-6-10
 */
public class PlayDemo {

    public static void main(String[] args) throws CloneNotSupportedException {

        // Generate a deck of playing cards and shuffle them
        Poker poker1 = new Poker();
        System.out.println("New: first deck in total "+poker1.getCardCount()+" Zhang:"+poker1.toString());

        Poker poker2= (Poker) poker1.clone();
        System.out.println("Copy the first deck to generate the second deck, total "+poker2.getCardCount()+" Zhang:"+poker2.toString());

        poker1.removeJoker();

        System.out.println("====The first deck takes away the queen and queen====");
        System.out.println("First deck and "+poker1.getCardCount()+" Zhang:"+poker1.toString());
        System.out.println("Second deck and "+poker2.getCardCount()+" Zhang:"+poker2.toString());

    }

}
  • Operation result:
    --In the first pair of objects, the "king of size" is removed, and in the second pair of cloned objects, the "king of size" is also removed

2.2 implementation method I of deep copy
  • The copied class needs to implement the Clonenable interface;
  • The clone() method is overridden, and the copy copy copy of reference type members is implemented autonomously.
    --We just need to rewrite the clone method in the Poker class to make the reference type members replicate:
/**
 * The whole deck of playing cards -- copy the reference variables independently
 *
 * @author zhuhuix
 * @date 2020-06-10
 */
public class Poker implements Cloneable, Serializable {

    private List<Card> cards;

    public Poker() {
        List<Card> cardList = new ArrayList<>();
        // Generate 52 playing cards according to the combination of decors and numbers
        for (int i = 0; i < Constant.COLORS.size(); i++) {
            for (int j = 0; j < Constant.NUMBERS.size(); j++) {
                cardList.add(new Card(Constant.COLORS.get(i), Constant.NUMBERS.get(j)));
            }
        }
        // Generate size King
        for (int i = 0; i < Constant.JOKER.size(); i++) {
            cardList.add(new Card("JOKER", Constant.JOKER.get(i)));
        }

        this.cards = cardList;
    }

    // Take the king from the whole deck of playing cards
    public void removeJoker() {
        Iterator<Card> iterator = this.cards.iterator();
        while (iterator.hasNext()) {
            Card cardJoker = iterator.next();
            if (cardJoker.getColor() == "JOKER") {
                iterator.remove();
            }
        }
    }

    public List<Card> getCards() {
        return cards;
    }

    public void setCards(List<Card> cards) {
        this.cards = cards;
    }

    public Integer getCardCount() {
        return this.cards.size();
    }

    @Override
    public String toString() {
        StringBuilder poker = new StringBuilder("[");
        Iterator<Card> iterator = this.cards.iterator();
        while (iterator.hasNext()) {
            poker.append(iterator.next().toString() + ",");
        }
        poker.setCharAt(poker.length() - 1, ']');
        return poker.toString();
    }

	// Traverse the collection of original objects and copy the generated objects
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Poker newPoker = (Poker)super.clone();
        newPoker.cards = new ArrayList<>();
        newPoker.cards.addAll(this.cards);
        return newPoker;
    }
}

  • Output results:
    --Through independent implementation of reference type replication, the reference type member address of the original object and the copy of the object is no longer associated
2.3 implementation method II of deep copy
  • Before using the second way to realize JAVA deep copy, we first understand the object copy of C + + program:
2.3.1 C + + copy constructor

C + + copy constructor, which has only one parameter, parameter type is the reference of this class, and is generally decorated with const

2.3.2 C + + source code
// Class definition of single card
// Created by Administrator on 2020-06-10.
//

#ifndef _CARD_H
#define _CARD_H

#include <string>

using namespace std;

class Card {
private :
    string color;
    string number;
public:
    Card();

    Card(const string &color, const string &number);

    const string &getColor() const;

    void setColor(const string &color);

    const string &getNumber() const;

    void setNumber(const string &number);

    string toString();

};


#endif //_CARD_H

// The implementation of single card class
// Created by Administrator on 2020-06-10.
//

#include "card.h"

Card::Card(){}

Card::Card(const string &color, const string &number) : color(color), number(number) {}

const string &Card::getColor() const {
    return color;
}

void Card::setColor(const string &color) {
    Card::color = color;
}

const string &Card::getNumber() const {
    return number;
}

void Card::setNumber(const string &number) {
    Card::number = number;
}


string Card::toString() {
    return getColor()+getNumber();
}




// Definition of playing cards
// Created by Administrator on 2020-06-10.
//

#ifndef _POKER_H
#define _POKER_H

#include <vector>
#include "card.h"

using namespace std;

const int COLOR_COUNT=4;
const int NUMBER_COUNT=13;
const int JOKER_COUNT=2;

const string COLORS[COLOR_COUNT] = {"♢", "♣", "♡", "♠"};
const string NUMBERS[NUMBER_COUNT]={"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};
const string JOKER[JOKER_COUNT] ={"Xiao Wang","king"};

class Poker {
private:
    vector<Card> cards;
public:
    Poker();

    Poker(const Poker &poker);

    const vector<Card> &getCards() const;

    void setCards(const vector<Card> &cards);

    int getCardCount();

    void toString();

    void clear();
};


#endif //_POKER_H

// The realization of playing cards
// Created by zhuhuix on 2020-06-10.
//

#include "Poker.h"
#include <iostream>

const vector<Card> &Poker::getCards() const {
    return this->cards;
}

void Poker::setCards(const vector<Card> &cards) {
    Poker::cards = cards;
}

// Constructor
Poker::Poker() {
    for (int i = 0; i < NUMBER_COUNT; i++) {
        for (int j = 0; j < COLOR_COUNT; j++) {
            this->cards.emplace_back(COLORS[j], NUMBERS[i]);
        }
    }
    for (int i = 0; i < JOKER_COUNT; i++) {
        this->cards.emplace_back("JOKER", JOKER[i]);
    }
}

// copy constructor 
Poker::Poker(const Poker &poker) {
    for (int i = 0; i < poker.getCards().size(); i++) {
        this->cards.emplace_back(poker.cards[i].getColor(), poker.cards[i].getNumber());
    }
}

int Poker::getCardCount() {
    return this->cards.size();
}

void Poker::toString() {
    cout << "common" << getCardCount() << "Cards:";
    cout << "[";
    for (int i = 0; i < this->cards.size(); i++) {
        cout << this->cards[i].toString();
        if (i != getCardCount() - 1) {
            cout << ",";
        }
    }
    cout << "]" << endl;

}

void Poker::clear() {
    this->cards.clear();
}

// Main test procedure
// Created by Administrator on 2020-06-10.
//

#include "Poker.h"
#include <iostream>

using namespace std;

int main() {
    Poker poker1;
    cout << "First deck:";
    poker1.toString();
    // Generate the second deck by copy constructor
    Poker poker2(poker1);
    cout << "Second deck:";
    poker2.toString();
    // Clear poker 1
    poker1.clear();
    cout << "Clear, first deck:";
    poker1.toString();
    cout << "Second deck:";
    poker2.toString();
    return 0;
}
  • Output:
2.3.3 JAVA realizes deep copy through copy construction method
  • The JAVA copy construction method is the same as the copy constructor of C + +. The class of the copied object needs to implement the copy construction method:
    --First you need to declare a parameter constructor with the same type as this class
    --Secondly, the copy construction method can realize fast copy through serialization
  • The copy object is created by calling the copy construction method.
    --Let's rewrite the Poker class to implement the copy construction method:
/**
 * The whole deck of playing cards -- a copy construction method
 *
 * @author zhuhuix
 * @date 2020-06-10
 */
public class Poker implements Serializable {

    private List<Card> cards;

    public Poker() {
        List<Card> cardList = new ArrayList<>();
        // Generate 52 playing cards according to the combination of decors and numbers
        for (int i = 0; i < Constant.COLORS.size(); i++) {
            for (int j = 0; j < Constant.NUMBERS.size(); j++) {
                cardList.add(new Card(Constant.COLORS.get(i), Constant.NUMBERS.get(j)));
            }
        }
        // Generate size King
        for (int i = 0; i < Constant.JOKER.size(); i++) {
            cardList.add(new Card("JOKER", Constant.JOKER.get(i)));
        }

        this.cards = cardList;
    }

    // Copy construction method: using serialization to realize deep copy
    public Poker(Poker poker) {

        try {

            ByteArrayOutputStream os = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(os);
            oos.writeObject(poker);

            ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(is);
            this.cards = ((Poker) ois.readObject()).getCards();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

    }

    // Take the king from the whole deck of playing cards
    public void removeJoker() {
        Iterator<Card> iterator = this.cards.iterator();
        while (iterator.hasNext()) {
            Card cardJoker = iterator.next();
            if (cardJoker.getColor() == "JOKER") {
                iterator.remove();
            }
        }
    }

    public List<Card> getCards() {
        return cards;
    }

    public void setCards(List<Card> cards) {
        this.cards = cards;
    }

    public Integer getCardCount() {
        return this.cards.size();
    }

    @Override
    public String toString() {
        StringBuilder poker = new StringBuilder("[");
        Iterator<Card> iterator = this.cards.iterator();
        while (iterator.hasNext()) {
            poker.append(iterator.next().toString() + ",");
        }
        poker.setCharAt(poker.length() - 1, ']');
        return poker.toString();
    }
}

  • Modify the main test program:
/**
 * Test procedure
 *
 * @author zhuhuix
 * @date 2020-6-10
 */
public class PlayDemo {

    public static void main(String[] args) throws CloneNotSupportedException {

        // Generate a deck of playing cards and shuffle them
        Poker poker1 = new Poker();
        System.out.println("New: first deck in total "+poker1.getCardCount()+" Zhang:"+poker1.toString());

        Poker poker2 = new Poker(poker1);
        System.out.println("Copy the first deck to generate the second deck of cards "+poker2.getCardCount()+" Zhang:"+poker2.toString());

        poker1.removeJoker();

        System.out.println("====The first deck takes away the queen and queen====");
        System.out.println("First deck and "+poker1.getCardCount()+" Zhang:"+poker1.toString());
        System.out.println("Second deck and "+poker2.getCardCount()+" Zhang:"+poker2.toString());


        Poker poker3 = new Poker(poker1);
        System.out.println("Third deck and "+poker3.getCardCount()+" Zhang:"+poker3.toString());
    }

}
  • Output results:
    --By means of serialization, deep copy of objects can also be realized

4, Summary

  • When copying objects in java programs, if there is a reference type in an object's class, deep copy is required
  • Object copying can be done by implementing the clonable interface
  • java programming can also imitate the copy constructor of C + + program, and realize the copy construction method to copy the object
  • Deep copy of objects can be realized by serialization and reordering

Tags: Java Programming

Posted on Wed, 10 Jun 2020 22:14:00 -0400 by FadeToLife