» »

[Java] array v voidu

[Java] array v voidu

Yacked2 ::

Pozdravljeni,

naletel sem na zanimiv pojav (vsaj zame). Če v main definiram neko spremenljivko x in jo nato podam kot parameter funkciji void, ki parameter nastavi na nekaj drugega, ta ista spremenljivka ostane v mainu še vedno x. Da bo bolj razumljivo:
public static void main(String[] args)
{
    int x = 5;
    spremeni(x);
    System.out.println(x);
}
public static void spremeni(int x)
{
    x = 10;
}

Po pričakovanju se mi izpiše 5.

Ampak če kodo malo modificiram in namesto int vzamem array, torej:

public static void main(String[] args)
{
    int[] x = {5};
    spremeni(x);
    System.out.println(x[0]);
}
public static void spremeni(int[] x)
{
    x[0] = 10;
}

To pa po čudežu izpiše 10.

Najprej sem mislil, da je to zaradi objekta a se tudi Integer in String obnašata "pričakovano".

Prav tako se array obnaša "čudno", če ga kopiram.

Normalno obnašanje
int x = 5;
int y = x;
x = 10;
//Sedaj je y=5 in x=10


Arrayi
int[] x = {5};
int[] y = x;
x[0] = 10;
//Sedaj je y={10} in x={10}


Ima torej kdo kakšno razlago zakaj se to dogaja ? In predvsem kako to onemogočiti, saj sem navajen, da če imam lokalne spremenljivke in fukcija nič ne vrača, naj bi parametre v mainu pustila pri miru, a v primeru arrayev očitno ni tako.

Lp
Yacked2
Korak naprej ni vedno ustrezen...sploh če si na robu prepada!

fiction ::

Jinto ::

Yacked2 je izjavil:


Arrayi

int[] x = {5};
int[] y = x;
x[0] = 10;
//Sedaj je y={10} in x={10}



x in y sta kazalca na strukturo v pomnilniku, y=x naredi to, da tudi y kaže na strukturo x. Se ne da spremenit.

jernejl ::

Za tvojo spremenljivko x je računalnik v pomnilniku rezerviral nek prostor na neki lokaciji.
Če je x primitivni tip (npr. int), bo na tej lokaciji zabeležena vrednost spremenljivke (recimo 5).
Če je x objekt (npr. Integer ali pa polje), bo na tej lokaciji pomnilniški naslov, kjer se dejansko nahaja objekt.

Ko spremenljivko pošlješ v funkcijo, potem funkcija dobi kopijo tistega, kar piše v pomnilniku na lokaciji x.
Pri primitivnih tipih tako funkcija prejme kopijo vrednosti, pri objektih pa kopijo naslova, kjer se objekt dejansko nahaja.

Glede Integerja in zakaj se obnaša "pričakovano" (verjetno bo iz slik bolj jasno, kaj se v ozadju dogaja):
http://stackoverflow.com/questions/1606...

lebdim ::

A se mogoče reče temu pojavu "problem frfotajočih referenc"? ;)
Ne vem, zakaj imam v spominu, da je to ta problem ...

Zgodovina sprememb…

  • spremenil: lebdim ()

Yacked2 ::

Najlepša hvala za odgovore, torej arraye se kopira kot int[] nova = stara.clone(); Torej pri objektih moram pazit na te zadeve. Samo pri String je pa spet vrednost, verjetno se lahko orientiram tako, da pogledam kaj izpiše System.out.println(objekt), če izpiše tekst delam z vrednostmi, če dobim pa tisto hex kodo delam pa s pointerji ?
Korak naprej ni vedno ustrezen...sploh če si na robu prepada!

Spura ::

Kva? Prvo je to, da v javi ni pointerjev, ampak so reference.
Drugo je to, da absolutno nisi razumel. To, kateri classi imajo overridan toString nima veze z ničemer.
Vleces razlike tam, kjer jih ni.

Pri klicih funkcij se argumenti kopirajo. Vsi argumenti. Torej v javi imaš samo pass-by-value.

String s = "x";

Temu ljudje recejo deklaracija spremenljivke tipa String, kar ni res. To je deklaracija spremenljike tipa referenca na String object.
In ravno tako kot int, float ipd se ta spremenljika kopira ob klicu funkcije. Vrednost, ki se kopira, torej vrednost spremenljike tipa referenca na String je referenca sama, ne pa objekt.

To je to.

In iz tega logicno izhaja nekaj stvari:

1. Znotraj funkcije spremembe vrednosti spremenljike ne vplivajo na vrednost zunaj funkcije:

	private void function(int x, int[] y, String z, List<String> myList) {
		x = 3;
		y = new int[] {10};
		z = "BLA";
		myList = new ArrayList<String>();
	}


2. Znotraj funkcije lahko, ce je vrednost spremenljike referenca, dostopamo do objekta preko nje, in spreminjamo polja na objektu samem ali klicemo funkcije, ki spremenijo polja. Spremembe seveda ostanejo tudi po zakljucku funkcije, ker smo spremenili objekt. To ni isto, kot spremeba vrednosti reference.

Torej naslednji primeri ne spreminjajo vrednosti argumentov funkcije, ampak dostopajo do objektov in spreminjajo objekte.

	private void function(int x, int[] y, String z, List<String> myList) {
		// Dostopamo do arraya in spreminjamo njegovo vsebino
		y[0] = 10;
		// String objet nima nobenega polja ki bi se ga dalo spreminjati,
		// niti nima nobene funkcije, ki bi objekt spreminjala.
		
		// Dostopamo do lista in spreminjamo njegovo vsebino preko funkcije
		myList.add("BLA");
	}

technolog ::

Probaj Integer namesto int in opazuj.

kr?en ::

To kar je Spura napisal.

Ostalo je nepomembno.

Mavrik ::

Spura - začetnik bi te vprašal - zakaj pa se potem String ne spremeni? :) Pa Integer?
The truth is rarely pure and never simple.

Spura ::

technolog je izjavil:

Probaj Integer namesto int in opazuj.

Isti kurac je, ker je Integer immutable.

Mavrik je izjavil:

Spura - začetnik bi te vprašal - zakaj pa se potem String ne spremeni? :) Pa Integer?

Ker spreminjas referenco, da referencira drug String objekt. Ne spreminjas Stringa.

Kot sem napisal v komentarju

// String objekt nima nobenega polja ki bi se ga dalo spreminjati,
// niti nima nobene funkcije, ki bi objekt spreminjala.

Zgodovina sprememb…

  • spremenil: Spura ()


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

Java passing

Oddelek: Programiranje
203283 (2936) mihibo5
»

Java metode;

Oddelek: Programiranje
354539 (3731) ragezor
»

[Java] Castanje

Oddelek: Programiranje
91435 (1290) fiction
»

Rekurzija v javi z ArrayList

Oddelek: Programiranje
81459 (1302) marjan_h
»

C# je mozna referenca do int izven funkcije (direkt v classu torej)

Oddelek: Programiranje
81544 (1358) TopCat

Več podobnih tem