Skip to content

Instantly share code, notes, and snippets.

@pjastr
Last active November 15, 2017 16:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pjastr/3ffc3b8e066265f9e44ac33ac778c3c4 to your computer and use it in GitHub Desktop.
Save pjastr/3ffc3b8e066265f9e44ac33ac778c3c4 to your computer and use it in GitHub Desktop.

Kopiowanie

Operator przypisania

Operator przypisania zastosowany do typu wartościowego.

        int a = 6; //deklaracja i nadanie wartości a na 6
        int b = a; //skopiowanie za pomocą operatora przypisania

        // wyświetlenie wartości a i b po skopiowaniu
        System.out.println("a="+a+", b="+b);

        b++; //inkrementacja zmiennej b

        //wyświetlenie wartości a i b po zmianie
        System.out.println("Po zmianie");
        System.out.println("a="+a+", b="+b);

Na konsoli otrzymamy:

a=6, b=6
Po zmianie
a=6, b=7

Operator przypisania zastosowany do typu referencyjnego.

W naszym projekcie dodajemy sobie klasę Osoba.

public class Osoba {
    private int wiek; //deklaracja pola
    public Osoba() { } //konstruktor domyślny
    public Osoba(int wiek) //konstruktor parametryczny
    {
        this.wiek = wiek;
    }
    public void UstawWiek(int wiek) //metoda na ustawienie wieku
    {
        this.wiek = wiek;
    }
    public int PobierzWiek() //metoda na pobranie wieku
    {
        return wiek;
    }
}

Kod programu w Main:

        Osoba o1 = new Osoba(30); //tworzy pierwszy obiekt i nadajemy mu wiek 30
        Osoba o2 = new Osoba(); //tworzymy drugi obiekt
        o2 = o1; //kopiowanie za pomocą operatora przypisania

        //wartości po kopiowaniu
        System.out.println("Wiek pierwszej osoby "+ o1.PobierzWiek());
        System.out.println("Wiek drugiej osoby "+o2.PobierzWiek());

        o1.UstawWiek(31); //zmiana wieku pierwszej osoby

        //wartości po zmianie
        System.out.println("Po zmianie");
        System.out.println("Wiek pierwszej osoby "+ o1.PobierzWiek());
        System.out.println("Wiek drugiej osoby "+ o2.PobierzWiek());

        //sprawdzenie referencji
        if (o1 == o2)
            System.out.println("Referencje odwołują się do tego samego obiektu");
        else
            System.out.println("Referencje nie odwołują się do tego samego obiektu");
Wiek pierwszej osoby 30
Wiek drugiej osoby 30
Po zmianie
Wiek pierwszej osoby 31
Wiek drugiej osoby 31
Referencje odwołują się do tego samego obiektu

Płytka kopia

Płytką kopię używamy, kiedy klasa nie zawiera pól referencyjnych.

Klasa dziedziczy po interfejsie Cloneable i implementuje metodę clone(), w której wykorzystamy metodę super.clone().

Modyfikujemy klasę Osoba:

public class Osoba implements Cloneable {
    private int wiek; //deklaracja pola
    public Osoba() { } //konstruktor domyślny
    public Osoba(int wiek) //konstruktor parametryczny
    {
        this.wiek = wiek;
    }
    public void UstawWiek(int wiek) //metoda na ustawienie wieku
    {
        this.wiek = wiek;
    }
    public int PobierzWiek() //metoda na pobranie wieku
    {
        return wiek;
    }

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

Zmodyfikowany kod w Main:

    public static void main(String[] args) throws CloneNotSupportedException {
        Osoba o1 = new Osoba(30); //tworzy pierwszy obiekt i nadajemy mu wiek 30
        Osoba o2 = new Osoba(); //tworzymy drugi obiekt
        o2 = (Osoba) o1.clone(); //kopiowanie za pomocą metody clone(), potem rzutujemy na klasę Osoba

        //wartości po kopiowaniu
        System.out.println("Wiek pierwszej osoby "+ o1.PobierzWiek());
        System.out.println("Wiek drugiej osoby "+o2.PobierzWiek());

        o1.UstawWiek(31); //zmiana wieku pierwszej osoby

        //wartości po zmianie
        System.out.println("Po zmianie");
        System.out.println("Wiek pierwszej osoby "+ o1.PobierzWiek());
        System.out.println("Wiek drugiej osoby "+ o2.PobierzWiek());

        //sprawdzenie referencji
        if (o1 == o2)
            System.out.println("Referencje odwołują się do tego samego obiektu");
        else
            System.out.println("Referencje nie odwołują się do tego samego obiektu");

    }
Wiek pierwszej osoby 30
Wiek drugiej osoby 30
Po zmianie
Wiek pierwszej osoby 31
Wiek drugiej osoby 30
Referencje nie odwołują się do tego samego obiektu

Płytka kopia dla klasy z polem referencyjnym

Tworzy klasę Urodziny na przechowywanie pola referencyjnego w klasie Osoba.

public class Urodziny {

    private String miejsceUr; //deklaracja pola
    public Urodziny() { } //konstruktor domyślny

    //konstruktor parametryczny
    public Urodziny(String miejsceUr)
    {
        this.miejsceUr = miejsceUr;
    }

    //metoda na ustawienie miejsca urodzin
    public void UstawMiejsceUr(String miejsceUr)
    {
        this.miejsceUr = miejsceUr;
    }

    //metoda na pobranie miejsca urodzenia
    public String PobierzMiejsceUr()
    {
        return miejsceUr;
    }
}

Zmodyfikowana klasa Osoba:

public class Osoba implements Cloneable {
    private int wiek; //deklaracja pola
    public Urodziny ur; //pole referencyjne

    //konstruktor domyślny (uzupełniamy o tworzenie obiektu)
    public Osoba()
    {
        ur = new Urodziny();
    }

    //konstruktor parametryczny
    public Osoba(int wiek,String miejsce)
    {
        this.wiek = wiek;
        ur = new Urodziny();
        ur.UstawMiejsceUr(miejsce);
    }

    public void UstawWiek(int wiek) //metoda na ustawienie wieku
    {
        this.wiek = wiek;
    }

    public int PobierzWiek() //metoda na pobranie wieku
    {
        return wiek;
    }

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

Kod w Main modyfikujemy tylko w konstuktorze Osoby. Wyjście poniżej. Modyfikacja samego wieku daje pożądany "efekt kopiowania".

Wiek pierwszej osoby 30
Wiek drugiej osoby 30
Po zmianie
Wiek pierwszej osoby 31
Wiek drugiej osoby 30
Referencje nie odwołują się do tego samego obiektu

Jeśli w Main zmodyfikujemy również miejsce urodzin, nie będzie to co chcemy.

    public static void main(String[] args) throws CloneNotSupportedException {
        Osoba o1 = new Osoba(30,"Olsztyn"); //tworzy pierwszy obiekt i nadajemy mu wiek 30
        Osoba o2 = new Osoba(); //tworzymy drugi obiekt
        o2 = (Osoba)o1.clone(); //kopiowanie za pomocą metody Clone(), potem rzutujemy na klasę Osoba

        //wartości po kopiowaniu
        System.out.println("Wiek pierwszej osoby "+ o1.PobierzWiek());
        System.out.println("Miejsce urodzin pierwszej osoby "+ o1.ur.PobierzMiejsceUr());
        System.out.println("Wiek drugiej osoby "+o2.PobierzWiek());
        System.out.println("Miejsce urodzin drugiej osoby "+ o2.ur.PobierzMiejsceUr());

        o1.UstawWiek(31); //zmiana wieku pierwszej osoby
        o1.ur.UstawMiejsceUr("Gdańsk"); //zmiana miejsca urodzin pierwszej osoby

        //wartości po zmianie
        System.out.println("Po zmianie");
        System.out.println("Wiek pierwszej osoby "+ o1.PobierzWiek());
        System.out.println("Miejsce urodzin pierwszej osoby "+ o1.ur.PobierzMiejsceUr());
        System.out.println("Wiek drugiej osoby "+ o2.PobierzWiek());
        System.out.println("Miejsce urodzin drugiej osoby "+ o2.ur.PobierzMiejsceUr());

        //sprawdzenie referencji
        if (o1.ur == o2.ur)
            System.out.println("Referencje odwołują się do tego samego obiektu");
        else
            System.out.println("Referencje nie odwołują się do tego samego obiektu");
    }

Wyjście:

Wiek pierwszej osoby 30
Miejsce urodzin pierwszej osoby Olsztyn
Wiek drugiej osoby 30
Miejsce urodzin drugiej osoby Olsztyn
Po zmianie
Wiek pierwszej osoby 31
Miejsce urodzin pierwszej osoby Gdańsk
Wiek drugiej osoby 30
Miejsce urodzin drugiej osoby Gdańsk
Referencje odwołują się do tego samego obiektu

Głęboka kopia

Głęboką kopię stosujemy do klas z polami referencyjnymi.

Modyfikujemy kod klasy Osoba:

public class Osoba {
    private int wiek; //deklaracja pola
    public Urodziny ur; //pole referencyjne

    //konstruktor domyślny (uzupełniamy o tworzenie obiektu)
    public Osoba()
    {
        ur = new Urodziny();
    }

    //konstruktor parametryczny
    public Osoba(int wiek,String miejsce)
    {
        this.wiek = wiek;
        ur = new Urodziny();
        ur.UstawMiejsceUr(miejsce);
    }

    public void UstawWiek(int wiek) //metoda na ustawienie wieku
    {
        this.wiek = wiek;
    }

    public int PobierzWiek() //metoda na pobranie wieku
    {
        return wiek;
    }

    public Osoba GlebokaKopia() //implementacja głębokiej kopii
    {
        Osoba tempOsoba = new Osoba();
        tempOsoba.wiek = this.wiek;
        tempOsoba.ur.UstawMiejsceUr(this.ur.PobierzMiejsceUr());
        return tempOsoba;

    }
}

Kod w Main:

    public static void main(String[] args)  {
        Osoba o1 = new Osoba(30,"Olsztyn"); //tworzy pierwszy obiekt i nadajemy mu wiek 30
        Osoba o2 = new Osoba(); //tworzymy drugi obiekt
        o2 = o1.GlebokaKopia(); //kopiowanie za pomocą metody Clone(), potem rzutujemy na klasę Osoba

        //wartości po kopiowaniu
        System.out.println("Wiek pierwszej osoby "+ o1.PobierzWiek());
        System.out.println("Miejsce urodzin pierwszej osoby "+ o1.ur.PobierzMiejsceUr());
        System.out.println("Wiek drugiej osoby "+o2.PobierzWiek());
        System.out.println("Miejsce urodzin drugiej osoby "+ o2.ur.PobierzMiejsceUr());

        o1.UstawWiek(31); //zmiana wieku pierwszej osoby
        o1.ur.UstawMiejsceUr("Gdańsk"); //zmiana miejsca urodzin pierwszej osoby

        //wartości po zmianie
        System.out.println("Po zmianie");
        System.out.println("Wiek pierwszej osoby "+ o1.PobierzWiek());
        System.out.println("Miejsce urodzin pierwszej osoby "+ o1.ur.PobierzMiejsceUr());
        System.out.println("Wiek drugiej osoby "+ o2.PobierzWiek());
        System.out.println("Miejsce urodzin drugiej osoby "+ o2.ur.PobierzMiejsceUr());

        //sprawdzenie referencji
        if (o1.ur == o2.ur)
            System.out.println("Referencje odwołują się do tego samego obiektu");
        else
            System.out.println("Referencje nie odwołują się do tego samego obiektu");
    }

Wyjście:

Wiek pierwszej osoby 30
Miejsce urodzin pierwszej osoby Olsztyn
Wiek drugiej osoby 30
Miejsce urodzin drugiej osoby Olsztyn
Po zmianie
Wiek pierwszej osoby 31
Miejsce urodzin pierwszej osoby Gdańsk
Wiek drugiej osoby 30
Miejsce urodzin drugiej osoby Olsztyn
Referencje nie odwołują się do tego samego obiektu

Pytanie do przemyślenia (zaawansowane): czy operator == jest "najlepszy" do sprawdzania referencji obiektów? czy lepsza jest metoda equals? a może inna konstrukcja?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment