23 kwietnia 2015

Pass by Value

Jedną z fundamentalnych rzeczy jaką warto przyswoić sobie na początku przygody z Javą, jest sposób przekazywania dwóch rodzajów zmiennych: zmiennych podstawowych (prymitywnych) oraz zmiennych referencyjnych (obiektowych).

Content:
  • Czym jest zmienna podstawowa i referencyjna
  • Przekazywanie wartości innym zmiennym i metodom


Zmienna podstawowa i referencyjna


Zmienna podstawowa jest zmienną typu prostego (prymitywnego). Przetrzymują one w sobie wartości przypisane im podczas ich deklaracji. Takie typy to np. byte, short, int, boolean, long, double czy float.
int i = 5;
double d = 0.0;
byte b = 3;
short s = 7; 
Zmienna referencyjna to zmienna typu obiektowego. Są one swego rodzaju pojemnikami przetrzymującymi referencje do stworzonych podczas deklaracji obiektów. W żadnym wypadku nie można mówić, iż przetrzymują one w sobie konkretne obiekty! Przykładem takich typów może być np. String lub każdy inny obiekt reprezentujący klasę opisaną przy deklaracji.
String imie = new String("Ania");
String imie_2 = "Andrzej";
Date data = new Date();
SomeObject = new SomeObject();

Przekazywanie wartości innym zmiennym i metodom


Zmienne podstawowe
int a = 5;
int b = a; // kopiuje wartość zmiennej a i przypisuje ją zmiennej b
           // od teraz zmienna b nie ma wpływu na zmienną a

public void doSomething(int c){
  // wykonaj operację na c
}

doSomething(a); // kopiuje wartość zmiennej a(w tym przypadku 5)
                // do metody doSomething()
                // nie ma wpływu na zmienną a i b

Prześledźmy po kolei powyższy, nie skomplikowany przykład. W pierwszych dwóch liniach mamy przykład przekazania wartości z jednej zmiennej do drugiej. W efekcie otrzymamy dwie zmienne typu prostego int o wartości 5. Wykonanie operacji na zmiennej a, nie powoduje wpływu na zmienną b i odwrotnie!
Sytuacja jest bardziej przewrotna w momencie przekazywania takiej zmiennej do metody. Przy przekazywaniu zmiennej typu prymitywnego do metody również wykorzystujemy w metodzie tylko jej wartość. Ważne jest aby zapamiętać, iż metoda wykonująca operacje na tej wartości nie ma żadnego wpływu na pierwotną zmienną (metoda doSomething tworzy sobie własną zmienną [w tym przypadku int c], której przypisuje wartość zmiennej a i to właśnie na niej [zmienna c] wykonuje wszelkie operacje.

Zmienne referencyjne
Cat a = new Cat();
Cat b = a; // kopiuje referencje zmiennej a i przypisuje ją zmiennej b
           // od teraz obie zmienne mają wpływ na obiekt klasy Cat

public void doSomething(Cat c){
  // wykonaj operację na c
}

doSomething(a); // kopiuje referencję a do wykorzystania w
                // metodzie doSomething()
                // ma wpływ na obiekt Cat tak samo jak zmienna a i b

Prześledźmy ponownie lekko odmieniony kod. W pierwszych dwóch liniach przekazujemy referencję zmiennej a do zmiennej b. Różnica w porównaniu do zmiennych podstawowych wynika ze stworzenia podczas deklaracji obiektu Cat. Dlatego właśnie jest to typ referencyjny, gdyż przechowuje referencję do nowo powstałego obiektu, a nie jest tym obiektem. Po tej operacji mamy jeden obiekt klasy Cat oraz dwie referencje wskazujące na ten obiekt - a i b. Wykonanie operacji na zmiennej a i b powoduje wykonanie zmian na obiekcie do którego te referencje prowadzą!
W kolejnych liniach mamy zadeklarowaną metodę przyjmującą za parametr obiekt klasy Cat. Po przekazaniu zmiennej referencyjnej do metody zostaje stworzona kolejna referencja (w tym przypadku zmienna c), która wszystkie operacje będzie wykonywała na tym samym obiekcie klasy Cat, który został zainicjalizowany w pierwszej linii powyższego kodu.

Wyżej wymienione zależności opisuje się poprzez Pass by Value. W Javie wszystkie przekazania wykonują się za pomocą wartości! Dlatego niepoprawnym sformułowaniem jest często spotykane stwierdzenie przekazania obiektu (Pass by Object).

Brak komentarzy:

Prześlij komentarz