Output parameter

Předmět zaměřený na praktické programování v jazyku a prostředí Java
Lado
Matfyz(ák|ačka) level I
Příspěvky: 16
Registrován: 29. 1. 2007 11:42

Output parameter

Příspěvek od Lado »

Ahoj,
mam taky mensi problem s output parametrami. Chcem signalizovat error z nejakej metody ( cize zmenit boolean hodnotu ). Je jasne, ze pre boolean to nejde, lebo sa predava hodnotou. Ale pre Boolean by to malo ist - vid ukazka kodu

Kód: Vybrat vše

	public static void main(String[] args) {        
			Boolean a = Boolean.valueOf(true);
			System.out.println(a);
			skuska(a);
			System.out.println(a);		
		}
	
	private static void skuska(Boolean b) {
		b = false;
		System.out.println(b);
	}
Mozete hadat, coto vypise - true, false, true (!!!).
Vie mi to niekto vysvetlit? Vsade na nete pisu, ze by to malo dat true, false, false, ale akosi nedava.
Pre istotu
The Boolean class wraps a value of the primitive type boolean in an object. An object of type Boolean contains a single field whose type is boolean.
Osiris
Supermatfyz(ák|ačka)
Příspěvky: 403
Registrován: 11. 11. 2006 14:10
Typ studia: Informatika Mgr.
Bydliště: Praha
Kontaktovat uživatele:

Re: Output parameter

Příspěvek od Osiris »

Vždyť se to chová korektně! Uvědom si, že

Kód: Vybrat vše

   private static void skuska(Boolean b) {
      b = false;
      System.out.println(b);
   }
Ti do b dosadí novou referenci na jiný objekt. Jenže ty tu referenci předáváš HODNOTOU!
Osiris
Lado
Matfyz(ák|ačka) level I
Příspěvky: 16
Registrován: 29. 1. 2007 11:42

Re: Output parameter

Příspěvek od Lado »

Ok, dava to nejaky zmysel - otazka je, ako to upravit, aby sa to chovalo tak, ako ja chcem?
Osiris
Supermatfyz(ák|ačka)
Příspěvky: 403
Registrován: 11. 11. 2006 14:10
Typ studia: Informatika Mgr.
Bydliště: Praha
Kontaktovat uživatele:

Re: Output parameter

Příspěvek od Osiris »

Obávám se, že jde o immutable třídu, takže nijak.
Osiris
Osiris
Supermatfyz(ák|ačka)
Příspěvky: 403
Registrován: 11. 11. 2006 14:10
Typ studia: Informatika Mgr.
Bydliště: Praha
Kontaktovat uživatele:

Re: Output parameter

Příspěvek od Osiris »

Ale samozřejmě jde například vracet příslušná hodnota Boolean místo void.
Osiris
Lado
Matfyz(ák|ačka) level I
Příspěvky: 16
Registrován: 29. 1. 2007 11:42

Re: Output parameter

Příspěvek od Lado »

Osiris píše:Ale samozřejmě jde například vracet příslušná hodnota Boolean místo void.
Ano, to ide, ale toto je len priklad. V aplikacii mam uz navratovu hodnotu.
Tak ci tak, vdaka za vysvetlenie. Nenapadlo ma, ze pri b = false vznika novy objekt a ten sa tam priraduje. Som si myslel, ze sa len nastavi jeho hodnota ( pretazeny operator= ). Ale to su zle zvyky z C/C++/C# :)
t2
Matfyz(ák|ačka) level I
Příspěvky: 49
Registrován: 22. 1. 2006 15:19

Re: Output parameter

Příspěvek od t2 »

Ahoj

pri b = false nevznika novy objekt. Problem je, ze ty mas dve boolean premenne, jedna je v metode main a druha metode skuska. Pri zavolani skuska sa referencia odovzda hodnotou. Ale to ze zmenis kam referencia v metode skuska ukazuje (na false) nezmeni to, kam ukazuje referencia v metode main (na true). Pri zachovani semantiky tvojho programu to ide spravit tak, ze si tu boolean hodnotu zabalis do svojej triedy. Takto

Kód: Vybrat vše

public class A {
    
    static class ErrorState {
	boolean flag;
    }
    
    private static void skuska(ErrorState state) {
	state.flag = false;
	System.out.println(state.flag);
    }
    
    public static void main(String[] args) {       
        ErrorState errorState = new ErrorState();
        errorState.flag = true;
        System.out.println(errorState.flag);
        skuska(errorState);
        System.out.println(errorState.flag);      
     } 
    
}
Rozdiel je v tom, ze v celom programe sa pracuje len s jednou instanciou ErrorState, na ktoru ukazuju dve nezavisle referencie.

Inak ako bolo spomenute, krajsim a lepsim sposobom ako signalizovat chybu je vyhodit vynimku alebo pouzit navratovu hodnotu.
Betlista
Matfyz(ák|ačka) level I
Příspěvky: 24
Registrován: 21. 11. 2007 14:59
Typ studia: Informatika Mgr.

Re: Output parameter

Příspěvek od Betlista »

t2 píše:Ahoj

pri b = false nevznika novy objekt.
To nie je pravda, stačí si skúsiť:

Kód: Vybrat vše

public class BooleanOutput {

	static void skuska( Boolean b ) {
		Boolean old = b;
		b = true;
		System.out.println( old == b ); // false, takže nejsou stejné !!!
	}

	public static void main(String[] args) {
		Boolean b = false;
		System.out.println( b );
		skuska( b );
		System.out.println( b );
	}

}
Dôvod je jednoduchý v Jave 1.5 je

Kód: Vybrat vše

Boolean b = false;
iba náhražkou

Kód: Vybrat vše

Boolean b = new Boolean( false );
v jave 1.4 to bolo potreba písať, v 1.5 to uľahčili ale pre ľudí, ktorí si Javu 1.4 nezažili je to mätúce...
t2 píše:Problem je, ze ty mas dve boolean premenne, jedna je v metode main a druha metode skuska.
Toto tiež nie je pravda, veď si uvedom, že keby toto bola pravda, tak nefunguje ani ten Tvoj príklad. Objekty sa predávajú odkazom a primitívne typy hodnotou (predstav si, že by si do metódy predával obrovský objekt a on by sa celý najprv zduplikoval, to je dôvod prečo to nefunguje a to nehovorím o tom, že ani nie je jasné ako urobiť kópiu objektu), správne je to, čo písal kolega vyššie - wrapper typy sú immutable, teda nemeniteľné.

Okrem spôsobu s ErrorState existuje spôsob bez vytvárania novej triedy:

Kód: Vybrat vše

public class BooleanOutput {

	static void skuska2( Boolean[] b ) {
		b[0] = true;
	}

	public static void main(String[] args) {
		System.out.println( b );
		Boolean[] ba = new Boolean[] {b};
		skuska2( ba );
		System.out.println( ba[0] );
	}

}
ale ani tento spôsob by som nedoporučoval, z hľadiska OOP a dizajnu je správne, aby si urobil tzv. krabičku (Crate), ktorá obalí obe návratové hodnoty:

Kód: Vybrat vše

public class BooleanOutputCrate {

	static Crate skuska() {
		return new Crate( 10, false );
	}

	public static void main(String[] args) {
		skuska();
	}

	static class Crate {
		int i;
		boolean b;
		Crate( int i, boolean b ) {
			this.i = i;
			this.b = b;
		}
	}
}
Pretože output parametre sú nečitateľné pre niekoho, kto daný kód nepozná.
Odpovědět

Zpět na „PGR013 Java“