Referencja w Javie

0

Witam! Oto mój program:


public class Main {
	public static void main(String[] args){

		int i = 5;		
		Integer I = new Integer(i);
		Test.rob(i);
		Test.rob(I);

		 System.out.println(I);
		 System.out.println(i);
		
	}
}

class Test{
	public static void rob(Integer K){
		K = 44;
	}
	
	public static void rob(int k){
		k = 44;
	}	
	
}

W wyniku wyświetla się:
5
5
Skoro I jest obiektem i przekazuję je przez "referencje" do funkcji rob to dlaczego wynik nie jest:
44
5
Z góry dziękuję za pomoc.

0

w javie nie przekazuje sie przez referencje

0

I jest referencją, która jest przekazywana przez wartość.

Inaczej mówiąc:
I w main(...) jest zmienną przechowującą adres obiektu typu Integer. Przy wywołaniu Test.rob(...) zawartość tej zmiennej jest wrzucana (kolejny raz, bo zmienne lokalne są na stosie zawsze) na stos (przekazywanie referencji poprzez wartość) i w funkcji Test.rob(...) ta nowa zmienna jest dostępna jako parametr. Instrukcja K = 44 zmienia zawartość parametru, a zmienna I z funkcji main(...) pozostaje bez zmian, bo to przecież dwie różne zmienne.

Ponadto w miejscu gdzie jest instrukcja K = 44 dokonywany jest autoboxing. 44 jest typu int, ale od wersji 5 Javy kompilator automatycznie używa odpowiedniej instrukcji do konwertowania int na Integer i Integer na int.

0

Dalej czegoś tu nie rozumiem. Czym różni się obiekt Integer od obiektu Test w tym przykładzie:


public class Main {
	public static void main(String[] args){
			Test t = new Test();
			t.zmienna = 5;
			Test.rob(t);
			System.out.println(t.zmienna);
		
	}
}

class Test{
	public int zmienna;
	
	public static void rob(Test K){
		K.zmienna = 44;
	}
	
	
}

Tu wyświetlona zostaje liczba 44. Tu nie występują, żadne kopie. wszystko jest na oryginale. Skąd ta równica? Czy obiekt Integer, Float itd. mają jakieś specjalne właściwości?

0

Tak, sprawdź jak wygląda implementacja klasy Integer to zobaczysz że ta klasa przechowuje informacje o instancjach o pewnych wartościach. W efekcie dwa Integery o tej samej wartości często mogą wskazywać fizycznie na ten sam obiekt. Na przykład wygląda to tak:

public static Integer valueOf(int i) {
  assert IntegerCache.high >= 127;
  if (i >= IntegerCache.low && i <= IntegerCache.high)
    return IntegerCache.cache[i + (-IntegerCache.low)];
  return new Integer(i);
}
0

Shalom, co ma piernik do wiatraka...

@marcin1991:
Nie widzisz różnicy pomiędzy tym:
foo = coś
a tym?
foo.bar = coś

W pierwszy wypadku zmieniasz wartość zmiennej LOKALNEJ foo na coś kompletnie innego...
W drugim przypadku odwołujesz się do obiektu, do którego referencja jest zapisana w foo i zmieniasz wartość czegoś W TYM OBIEKCIE

edit: lol <ort> zamiast

0

Shalom ma trochę racji i oczywiście Kerai też. Sprawa wygląda tak że w pierwszym przypadku co prawda przekazujesz referencje do obiekty Integer jednak w medodzie Test.rob(Integer) nie zmieniasz tego obiektu tylko powodujesz przypisanie do zmiennej lokalnej referencji innego obiektu, dlatego nie wskazuje ona już na obiekt z ciała metody main. Shalom miał racje z tym że klasa Integer ma pewne specyficzne własności, mianowicie, podobnie jaki inne typy wbudowane (Long, String itp), jest niezmienna to znaczy wartość raz utworzonego obiekty nigdy przez czas życia aplikacji nie zostanie zmieniona. Dlatego też lepszym sposobem na inicjalizacje zmiennej niż wywołanie konstruktora (new Integer(0)) jest skorzystanie ze statycznej metody którą przytoczył Shalom - dzięki temu wykorzystujemy już istniejące obiekty i unikamy tworzenia nowych niepotrzebnych.

2
marcin1991 napisał(a)

Witam! Oto mój program:


public class Main {
	public static void main(String[] args){

		int i = 5;		
		Integer I = new Integer(i);
		Test.rob(i);
		Test.rob(I);

		 System.out.println(I);
		 System.out.println(i);
		
	}
}

class Test{
	public static void rob(Integer K){
		K = 44;
	}
	
	public static void rob(int k){
		k = 44;
	}	
	
}

W wyniku wyświetla się:
5
5
Skoro I jest obiektem i przekazuję je przez "referencje" do funkcji rob to dlaczego wynik nie jest:
44
5
Z góry dziękuję za pomoc.

W java istnieje tylko przekazywanie przez wartosc. W momencie kiedy wywolujesz metode:

 
Test.rob(I);

tworzona jest KOPIA referencji I do obiektu Integer. Nadal pracujesz na tym samym obiekcie ale przez inna referencje. Dlatego jesli twoja metoda wyglada tak:

 
	public static void rob(Integer K){
		K = 44;
	}

to liczbe 44 przypisujesz do KOPI referencji ktora otrzymales jako argument. Po wykonaniu tej metody zmienna I w main() nadal wskazuje na Integer z wartoscia 5 a zmienna K wskazuje na obiekt Integer (dzieki autoboxingowi) o wartosci 44. Poniewaz nie zwracasz referencji K obiekt na ktory wskazuje zostanie w przyszlosci usuniety przez GC.

1 użytkowników online, w tym zalogowanych: 0, gości: 1