Przekazywanie parametru przez wartość i referencję

0

Cześć

Korzystam z poradnika 4prorammers dotyczącego "Przekazywanie parametru przez wartość i referencję" w odniesieniu do Javy.
Odnosząc się do tego zdania "Standardowo parametry funkcji (pod tym pojęciem rozumiem również metody w klasach) są przekazywane przez wartość. Czyli funkcja operuje na kopii zmiennej która została do niej przekazana." z wyżej wymienionego artykułu napisałem taki kod:

public class Testy4 
{


	public static void main(String[] args) 
	{
		
		
		int x = -1;
		foo(x);
		System.out.println(x);
		
		
	}
	static void foo(int x)
	{
		x = 34;
		System.out.println(x);
	}

} 

I wszystko się zgadza w odniesieniu do wyżej przytoczonego stwierdzenia - metoda

foo

bazuje na kopii zmiennej, pierwszy print to 34 a drugi to -1.
Ale już patrząc na ten kod tak nie jest:

 Public class MyClass
{
	public static void main(String[] args)
	{
		StringBuilder sb = new StringBuilder("Hello");
		System.out.println(sb);
		StringBuilder sb2 = sb;
		sb2.append(" World!");
		System.out.println(sb);
			
	}
}

Dlaczego tutaj metoda

append 

użyta na zmiennej sb2

sprawia, że zmienna referencyjna <code class="java">sb 

przyjmuje tutaj zainicjowaną wartość " World!"?

Czy chodzi o to, że przekazanie wartości przez wartość sprawia, że w metodzie działamy na kopii, a przekazanie przez referencje sprawia, że odnosimy się do bazowego obiektu?

2

W drugim przypadku nie ma żadnej mowy o parametrach. sb2 = sb = "Hello", czyli sb2 jest referencją do zawartości sb. Nie zachodzi żadne automagiczne kopiowanie obiektu sb. W takiej sytuacji wywołanie append na sb2 jest tożsame z wywołaniem tego na sb (oba wskazują na ten sam obiekt), więc dostajesz "Hello World!" w drugiej linijce.
Jeśli zrobiłbyś to samo przez metody i parametry, to efekt byłby identyczny, bo w parametrze leci tylko kopia zmiennej (czyli niejako kopiowany jest wskaźnik na obiekt), a nie całego obiektu.

1

Model w Javie jest najbliższy przekazywaniu przez wskaźnik w C++. Referencja w Javie jest jak wskaźnik w C++ i ona jest przekazywana przez wartość. Wyjątkiem są typu proste jak np. int, gdzie semantyka jest taka jak zwykłe przekazywanie przez wartość w C++.

0

A czy taki kod jest poprawny?

public class MyClass
{
	
	public static void main(String[] args)
	{		
		Integer x = new Integer(10);
		foo(x);
		System.out.println(x);
		
	}
	
	static void foo(Integer x)
	{
		x = 20;
		System.out.println(x);
	}
} 

Pytam w odniesieniu do tego, że mam w głowie stwierdzenie "Typy proste odpowiadają przekazywaniu przez wartość, a typy obiektowe to przekazywanie przez referencje". A z tego co zrobiłem wynika, że przekazałem typ obiektowy przez referencje. Coś źle rozumiem?

0

Skoro się kompiluje i wykonuje, to jest poprawny.
Moim zdaniem, wszystkie typy są przekazywane przez wartość, tylko co innego jest wartością dla typów prostych, a co innego dla obiektowych.

0

Czegoś dalej nie rozumiem:

public class MyClass
{
	
	public static void main(String[] args)
	{
		//Przykład 1
		StringBuilder sb = new StringBuilder("Hello");
		System.out.println(sb);
		StringBuilder sb2 = sb;
		sb2.append(" World!");
		System.out.println(sb);
		
		//Przykład 2
		Integer zmienna = new Integer(1);
		System.out.println(zmienna);
		Integer zmienna2 = zmienna;
		zmienna2++;
		System.out.println(zmienna2);
		System.out.println(zmienna);
}} 

W przykładzie pierwszym po użyciu metody append zmieni się wartość obiektu na który wskazują zmienne

sb

i sb2

. A w przykładzie drugim po inkrementacji tylko zmienna <code class="java">zmienn2

zwiększa swoją wartość. Jak to jest, że w pierwszym przykładzie dwie zmienne wskazują na ten sam obiekt i użycie metody append zmienia wartość danego obiektu, a w przypadku drugim już to tak nie działa?

0

Przypuszczam, że wytłumaczenie jest takie: operacja zmienna2++ wymaga "rozpakowania" - konwersji Integer na int. Po tej operacji następuje (zmienna2 jest typu Integer) "zapakowanie" - konwersja int na Integer. Bardzo prawdpodobne, że podczas tej drugiej konwersji wykorzystywany jest operator new.

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