Newsgroup: it.comp.java
Titolo: Strings passed by parameter or value?

Dear Friends,
As we all may be knowing that objects are passed by parameter in a Java
proggram in a object. Well  but the follwing piece od 
code contradicts it could you tell me why??
 
   class temp {
 
 
 
      public static void main(String args[])
 
      {
         temp t=new temp();
         String g=new String("vikram");
         t.change(g);
         System.out.println(" the new value is "+g);
      }
 
 
      void change(String a)
 
      {
         a="vivek";
      }
   }
I mean the output should be "vivek" , whereas it is coming out to be
"vikram". Could you tell me why??
Any type of help would be highly appreciated
Vikram
--
Give It A Thought:
The word IMPOSSIBLE itself means "I M POSSIBLE".
----Anonymous
"Hard work never killed anybody" But why take the risk !
(I don't want to be an exception!)
----Vikram
                          \\\\/////
                          / ^   ^ \
  ____                   ( (o) (o) )                       ____
 ( __ )---------------oOOO---(_)-----OOOo-----------------( __ )
  |  |                                                     |  |
  |  |                   Vikram Kumar                      |  |
  |  |                                                     |  |
  |  |      mailto:
vik...@employees.org
                    |  |
  |  |                                                     |  |
  |  |      
http://www.employees.org/~vikram
               |  |
  |  |      
http://members.tripod.com/~Coolviki
            |  |
  |  |                                                     |  |
  |  |                                                     |  |
  |__|                                                     |__|
 (____)---------------------------------------------------(____)

 "vikram". Could you tell me why??
Because the assignment is lost. If I remember correctly how a compiler
works, and if Java works only a little bit like an ordinary compiler -and
it should-, you pass a reference to a String object held in 'g' pushing it
in the stack to the function change(); the function pops the stack finding
a reference to the string "vikram" and puts it into the String object 'a',
and then you change the reference in 'a' to another String object
("vivek"). Then you do nothing with the changed object.
You should declare the String g object as a class property to be able to
change it via multiple methods.
If, as always, I am wrong in something, please correct me.
Ciao,
 Stefano
----------
"X WindowSSS, teSSSoro mio... lo odieremo per SSSempre"
Bill Gollum
----------

 ...
Java passes all by-value, if you pass prmitives they are duplicated, if you
pass handles they are duplicated too! But an handle it's not an object,
it's a pointer to an object, so the effect is that object are passed "by
reference" (because it's a copy of the value, but the value of the pointer
is itself a reference). This is to explain the terminology headache: Sun
prefer to say objects are passed by reference and primitives by value
because they want to hide the fact they use pointers...
So, correctly, you expected the code above to change the value of your
String, because String is an object and so is passed "by reference" (in the
Sun way):  "a" it's an "alias" of "g", so "a" it's a pointer pointing to
same value. But the Design of Strings implements the Immutable Pattern, for
various reasons: a String CANNOT be changed, and every operation that seems
to do so, really only creates a new object with the value "changed". When
you are doing a ="xxxx", you are saying a = new String("xxx"), so "a" it's
not more an alias of "g", and "g" stays the same.
There are some other strange behaviours for Strings and Arrays, and this is
due to their hybrid nature of objects and "primitives". You can se my
online "Java basic/intermediate test" for more examples of this (at
http://www.ugolandini.net
)
bye
Ugo
__________________________________________________________________________
"La perfezione si ottiene non quando non c'è nient'altro da aggiungere,
 bensì quando non c'è più niente da togliere." Antoine de Saint-Exupéry
__________________________________________________________________________
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Enterprise Java Consulting
@mail: Ugo.L...@Flashnet.it
Home Page: 
http://www.ugolandini.net
Mentoring: 
http://www.projectoo.com
Work Phone: 02/61860647-6-4 06/58332267
Cell Phone: 0347/6310749 - 0347/4783580
Fax Phone: 02/700 413 187
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


non sono sicuro di aver capito bene la tua teoria.
Comunque, supponiamo di avere una classe A e di utilizzarla al posto di String
nel codice di Vikram.
public class A {
  public A(int i) {
    value = i;
  }
  public void set(int i){
    value = i;
  }
  public int get(){
    return value;
  }
  private int value;
}
e quindi il codice diVikram tramutato in:
public class Passing {
  public static void main(String[] args) {
    Passing passing = new Passing();
    A a1 = new A(100);
    passing.change(a1);
    System.out.println("Valore: " + a1.get());
  }
  public void change(A a2){
    a2.set(500);
  }
}
L'output è 100 o 500 secondo te? ;)
--


 L'output è 100 o 500 secondo te? ;)
E' ovviamente 500 in questo caso. Ti spiego, però occhio che l'esame di linguaggi
e compilatori l'ho dato qualche (?) anno fa, quindi non ho più la mente ben
fresca... e ieri sera certo non sono andato a rileggermi il mio vecchio libro di
testo. :)) Allora: normalmente un compilatore produce codice che passa i parametri
alle funzioni via stack (lasciamo perdere le ottimizzazioni che passano i
parametri direttamente sui registri e rimaniamo sul classico, tipo la funzione
printf() del C). Quindi il codice di Vikram produrrebbe (se compilato dal C
almeno) il seguente (pseudo)codice, supponendo che quando si chiama un metodo il
riferimento all'oggetto vada nel registro A0 ed i parametri poi vengano letti nei
rimanenti registri A1..A7,D0...D7 (MC68000):
   class temp {
      public static void main(String args[]) {
         temp t=new temp();
         String g="vikram"; // Semplifichiamo un po' le chiamate o vado ai matti
         t.change(g);
         System.out.println(" the new value is "+g); // Non sarà tradotto! :)
      }
      void change(String a) {
         a="vivek";
      } // Già ad occhio si vede che questa assegnazione andrà smarrita...
   }
main:
    # ... = new temp();
    # (Crea spazio sullo stack per tenere una nuova struttura di tipo 'temp' e di
dimensione 0, visto che non ha nessuna proprietà)
    MOVE SP, 0(SP) #è parecchio semplificato, l'ho allocato direttamente sullo
stack invece di chiamare un costruttore ecc ecc... Vedi sotto la traduzione del
tuo codice semmai...
    # temp t = ...
    LEA SP, A0 (Carica l'indirizzo effettivo della struttura dentro A0)
    MOVE A0, -(SP) (Memorizza A0 dentro lo stack)
    # String g = "vikram"
    LEA vikram, A0 (Carica l'indirizzo effettivo di "vikram"...)
    MOVE A0, -(SP) (..e lo memorizza nello stack)
    MOVE 8(SP), A0 (Recupera l'indirizzo di t per passarlo ad una funzione)
    MOVE 4(SP), A1 (Prende l'indirizzo della stringa "vikram")
    PUSH A1 (lo mette nello stack)
    PUSH A0 (lo mette nello stack)
    JSR change (Salta al metodo change)
    ...
    // Chiamata al System.out.println(...)
   RTS (Ritorno dal metodo main)
   // Fine esecuzione del programma
change:
    POP A0 (Recupera un riferimento ad un oggetto di tipo temp e lo mette in A0;
in questo momento la struttura è t -ma va? :)- )
    POP A1 (Recupera un parametro di tipo String e lo mette in A1, la stringa in
questo momento è "vikram")
    LEA vivek, A1 (Carica l'indirizzo di "vivek" in A1)
    RTS (E torna. Come vedi, di caricare l'indirizzo di "vivek" non me ne poteva
fregar di meno)
vikram:
    DC.B "vikram", 0 (Dichiara una manciata di bytes contenenti la stringa in
questione
vivek:
    DC.B "vivek", 0 (Dichiara una manciata di bytes contenenti la stringa in
questione
**********
Il tuo codice invece si potrebbe tradurre (molto semplificato) come:
    #public class A {
    #    public A(int i) {
    #        value = i;
    #    }
_A_constructor:
    MOVE (SP)+, D0 #recupera int i in D0, a questo giro non ho un puntatore ad un
oggetto String ma ad un tipo primitivo, quindi lo carico via un registro dati
    MOVE SP, -4(SP) # alloca spazio per una struttura A di 4 bytes - quant'è int
sotto java? 2 o 4 bytes? vabbè, comunque -
    LEA SP, A0 # carica l'indirizzo della struttura in A0
    MOVE D0, (A0) # memorizza value = i ossia il contenuto di D0 dentro la
locazione puntata da A0
    RTS #fine metodo
   #public void set(int i){
    #    value = i;
    #}
_A_set:
    POP A0 #recupera il riferimento alla struttura
    POP D0 #recupera int i
    MOVE D0,(A0) #memorizza l'intero dentro la struttura
    RTS #torna
    #public int get() {
    #    return value;
    #}
_A_get:
    POP A0 #recupera il riferimento alla struttura
    MOVE (A0), D0 #recupera, partendo dal riferimento, il contenuto di value
    MOVE D0,-(SP) #lo infila nello stack per restituirlo al chiamante
    RTS #torna
    #private int value;
    #viene tenuto dentro 4 bytes allocati dal costruttore
    #}
e quindi il codice diVikram tramutato in:
    #public class Passing {
    #    public static void main(String[] args) {
    #        Passing passing = new Passing();
    MOVE SP, 0(SP) #memorizza una struttura Passing (vuota) //Anche qui non ho
scritto il costruttore ma ho semplificato, abbiate pazienza
    LEA SP,A0
    MOVE A0,-(SP)
    #        A a1 = new A(100);
    MOVE #100, -(SP)
    JSR _A_constructor
    MOVE (SP)+,A0 #recupera il riferimento alla struttura riportato dal
costruttore di A
    MOVE A0,-(SP) #e lo memorizza nello stack. Spreco di due istruzioni a vs
parere? Il codice NON e' ottimizzato, non è colpa mia. ;)
    #        passing.change(a1);
    MOVE 4(SP),A1 #recupera il riferimento ad a1
    MOVE A1,-(SP)
    MOVE 8(SP),A0 #recupera il riferimento a passing
    MOVE A0,-(SP)
    JSR _A_change
    #        System.out.println("Valore: " + a1.get());
    MOVE 4(SP),A0
    MOVE A0, -(SP)
    JSR _A_get
    MOVE (SP)+,D0 #in D0 abbiamo 500
    #System.out.println(500)
    #non me lo fate tradurre per carità :)
    #    }
    #    public void change(A a2){
    MOVE (SP)+,A0 #recupera il riferimento a se stesso (this)
    MOVE (SP)+,A1 #recupera il riferimento ad una struttura A
    #        a2.set(500);
    MOVE #500,-(SP) #memorizza 500 nello stack
    MOVE A1,-(SP) #memorizza il riferimento ad a2 nello stack
    JSR _A_set
    RTS
    #    }
    #}
**********
Qual'è la differenza tra i due? Se segui il codice, in pratica vedrai che mentre
nel programma di Vikram il valore (puntatore) viene passato, poi cambiato, e
quindi non scritto da nessuna parte e quindi perso, nel tuo viene infilato nella
struttura puntata da A0. E quindi mentre lui ottiene "vikram" invece di "vivek",
tu ottieni correttamente 500.
Ti ringrazio di avermi dato la possibilità di rispolverare il mio 68000 anche se,
dopo qualche anno, chissà che bestialità avrò scritto tra i LEA e i MOVE...
speriamo poche! Non l'ho neppure assemblato!!! :) Come sta il bambino? Il mio mi
sta finendo la carta della stampante con La Bottega Dei Giochi di Tarzan...
occhio! ;)


 occhio! ;)
Il mio ha 4 mesi, il massimo che fa è pestare casualmente sulla tastiera producendo
dei fantastici  "wei  o f  h     dnw90zxsfg uis  a  D     8 2  13ì", i suoi primi
tentativi di programmare con le espressioni regolari!!!


 </OT>
Accumulatore? :) Vado a rispolverarmi l'assembler Z80 e poi faccio il porting di Java su
ZX Spectrum! ;)


code contradicts it could you tell me why??
Java function call semantics is - like C - always by value, which means that 
new *copies* of the passed parameters are created in the called method' stack. 
Thus, passing a String reference to a function implies creating a new copy of 
the reference on the caller' stack. You then reassign this reference to a point 
to a different String object, but the original reference stays unchanged. 
A String object is intended as an object which doesn't change after 
construction - pretty much like the primitive type carriers (Integer, Double, 
etc). Note that Strings don't provide a *set* method whatsoever; if u want a 
"changeable" string you should either use StringBuffer or create a new class 
embedding a String object. 
-- 
God is Real, unless declared Integer.
ObjectZone - 
http://space.tin.it/computer/csadun/