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
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ł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
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łę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?