when using Class type as method parameters, I have a question...

Discussion in 'Java' started by www, Nov 7, 2007.

  1. www

    www Guest

    Hi,

    I thought I have understood this issue without any problems already.
    When using class type parameters for a method, the behavior is kind of
    like pass-by-reference. The object can be modified by the code inside
    the method, right? But today, I ran into an interesting problem: the
    object cannot get the change it wants.

    Suppose I have a class called Species. I have a method

    //oldSpecies is an object of Species, its content has been set already.
    //newSpecies is an object of Species, but its content has not been set
    yet. i.e. its content all has been set by the default values. The
    purpose of this method is to set newSpecies content based on different
    condition.
    public static void convertOldSpeciesToNewSpecies(Species oldSpecies,
    Species newSpecies)
    {
    if(..) //BLOCK A
    {
    newSpecies = oldOne; //just assign it. Here is the problem! The
    caller, the second parameter, does not get the value
    }
    else //BLOCK B
    {
    //in this case, newSpecies get assigned values. No problem, the caller
    gets the value.
    newSpecies.setXXX
    newSpecies.setYYY

    }

    //print out newSpecies content
    System.out.println(newSpecies.toString());
    }


    Helper.convertOldSpeciesToNewSpecies(speciesOne, speciesTwo);

    Above calling, if the condition fits BLOCK B, result is correct
    (speciesTwo gets the values it should get from inside the method).

    But if the condition fits BLOCK A, speciesTwo does NOT get the content
    of speciesOne. The printing inside the method shows that newSpecies has
    got the correct content (same as speciesOne).

    What is the problem? Thank you very much.

    For my practical reason, I do not want to change the method to

    public Species getNewSpecies(Species oldSpecies){..}
    www, Nov 7, 2007
    #1
    1. Advertising

  2. www

    lyallex Guest

    www wrote:
    > Hi,
    >
    > I thought I have understood this issue without any problems already.
    > When using class type parameters for a method, the behavior is kind of
    > like pass-by-reference. The object can be modified by the code inside
    > the method, right? But today, I ran into an interesting problem: the
    > object cannot get the change it wants.
    >
    > Suppose I have a class called Species. I have a method
    >
    > //oldSpecies is an object of Species, its content has been set already.
    > //newSpecies is an object of Species, but its content has not been set
    > yet. i.e. its content all has been set by the default values. The
    > purpose of this method is to set newSpecies content based on different
    > condition.
    > public static void convertOldSpeciesToNewSpecies(Species oldSpecies,
    > Species newSpecies)
    > {
    > if(..) //BLOCK A
    > {
    > newSpecies = oldOne; //just assign it. Here is the problem! The
    > caller, the second parameter, does not get the value
    > }
    > else //BLOCK B
    > {
    > //in this case, newSpecies get assigned values. No problem, the
    > caller gets the value.
    > newSpecies.setXXX
    > newSpecies.setYYY
    >
    > }
    >
    > //print out newSpecies content
    > System.out.println(newSpecies.toString());
    > }
    >
    >
    > Helper.convertOldSpeciesToNewSpecies(speciesOne, speciesTwo);
    >
    > Above calling, if the condition fits BLOCK B, result is correct
    > (speciesTwo gets the values it should get from inside the method).
    >
    > But if the condition fits BLOCK A, speciesTwo does NOT get the content
    > of speciesOne. The printing inside the method shows that newSpecies has
    > got the correct content (same as speciesOne).
    >
    > What is the problem? Thank you very much.
    >
    > For my practical reason, I do not want to change the method to
    >
    > public Species getNewSpecies(Species oldSpecies){..}


    I think I see what you are asking although your example is not very
    clear, you are using multiple names (newSpecies, oldSpecies, speciesOne,
    speciesTwo, oldOne and what have you) which confuses things a bit.

    Arguments to methods are passed call by value in Java, it just so
    happens that when you pass a reference in, the value is a memory
    address. In the method body, copies of the values are used so you will
    have a copy of (say) the memory address of newSpecies and a copy of the
    memory address of oldSpecies.

    Now to begin with, these copies still point to the original Objects so
    you can modify those objects directly by calling their methods, however
    if you assign one reference to another all you are doing is modifying
    the copies not the values (memory addresses) of the arguments.

    Write some more code to assign a value to a modified local copy and see
    if you can figure out what's going on, stick with it, you will get there
    in the end.
    lyallex, Nov 7, 2007
    #2
    1. Advertising

  3. www

    www Guest

    lyallex wrote:


    > Arguments to methods are passed call by value in Java, it just so
    > happens that when you pass a reference in, the value is a memory
    > address. In the method body, copies of the values are used so you will
    > have a copy of (say) the memory address of newSpecies and a copy of the
    > memory address of oldSpecies.
    >
    > Now to begin with, these copies still point to the original Objects so
    > you can modify those objects directly by calling their methods, however
    > if you assign one reference to another all you are doing is modifying
    > the copies not the values (memory addresses) of the arguments.
    >


    Thank you for your help. Now I understand it:

    public static void convertOldSpeciesToNewSpecies(Species oldSpecies,
    Species newSpecies){..}

    Helper.convertOldSpeciesToNewSpecies(speciesOne, speciesTwo);

    Now, oldSpecies has the memory address of the object speciesOne,
    newSpecies has the memory address of the object speciesTwo.

    If condition is such so that goes to BLOCK A, newSpecies has the memory
    address of the object speciesOne, due to the code BLOCK A. *BUT*, the
    object speciesTwo remain un-modified. That is why speciesTwo didn't get
    what it should get after the method calling.
    www, Nov 7, 2007
    #3
  4. www

    lyallex Guest

    www wrote:
    > lyallex wrote:
    >
    >
    >> Arguments to methods are passed call by value in Java, it just so
    >> happens that when you pass a reference in, the value is a memory
    >> address. In the method body, copies of the values are used so you will
    >> have a copy of (say) the memory address of newSpecies and a copy of
    >> the memory address of oldSpecies.
    >>
    >> Now to begin with, these copies still point to the original Objects so
    >> you can modify those objects directly by calling their methods,
    >> however if you assign one reference to another all you are doing is
    >> modifying the copies not the values (memory addresses) of the arguments.
    >>

    >
    > Thank you for your help. Now I understand it:
    >
    > public static void convertOldSpeciesToNewSpecies(Species oldSpecies,
    > Species newSpecies){..}
    >
    > Helper.convertOldSpeciesToNewSpecies(speciesOne, speciesTwo);
    >
    > Now, oldSpecies has the memory address of the object speciesOne,
    > newSpecies has the memory address of the object speciesTwo.
    >
    > If condition is such so that goes to BLOCK A, newSpecies has the memory
    > address of the object speciesOne, due to the code BLOCK A. *BUT*, the
    > object speciesTwo remain un-modified. That is why speciesTwo didn't get
    > what it should get after the method calling.
    >


    It takes a while doesn't it, but I reckon you are getting there.
    Keep at it, it's all worth it in the end :)
    lyallex, Nov 7, 2007
    #4
  5. www

    Roedy Green Guest

    On Wed, 07 Nov 2007 12:46:03 -0500, www <> wrote, quoted
    or indirectly quoted someone who said :

    > newSpecies = oldOne; //just assign it. Here is the problem! The
    >caller, the second parameter, does not get the value


    That will not work. That just makes newSpecies point to the same
    object that oldOne does. Any changes you make to the fields of
    newSpecies will modify the fields in oldOne.

    You need do something like this;

    newSpecies = oldOne.clone();

    See http://mindprod.com/jgloss/clone.html

    or

    newSpecies = new Species (oldOne);
    // a copy constructor

    or

    newSpecies = new Species();
    newSpecies.legCount = oldOne.legCount;
    ...

    Also be aware that if you make the parameter local variable point to a
    new object, it will have NO effect on the caller. You have either
    modify the object passed or return a reference to a new object.

    I think you would do well to invest some time reading a introductory
    Java textbook that explains these mysteries. Even a badly out of date
    second hand one (and hence very cheap) would do.

    --
    Roedy Green Canadian Mind Products
    The Java Glossary
    http://mindprod.com
    Roedy Green, Nov 7, 2007
    #5
  6. www

    Daniel Pitts Guest

    www wrote:
    > Hi,
    >
    > I thought I have understood this issue without any problems already.
    > When using class type parameters for a method, the behavior is kind of
    > like pass-by-reference. The object can be modified by the code inside
    > the method, right? But today, I ran into an interesting problem: the
    > object cannot get the change it wants.
    >
    > Suppose I have a class called Species. I have a method
    >
    > //oldSpecies is an object of Species, its content has been set already.
    > //newSpecies is an object of Species, but its content has not been set
    > yet. i.e. its content all has been set by the default values. The
    > purpose of this method is to set newSpecies content based on different
    > condition.
    > public static void convertOldSpeciesToNewSpecies(Species oldSpecies,
    > Species newSpecies)
    > {
    > if(..) //BLOCK A
    > {
    > newSpecies = oldOne; //just assign it. Here is the problem! The
    > caller, the second parameter, does not get the value
    > }
    > else //BLOCK B
    > {
    > //in this case, newSpecies get assigned values. No problem, the
    > caller gets the value.
    > newSpecies.setXXX
    > newSpecies.setYYY
    >
    > }
    >
    > //print out newSpecies content
    > System.out.println(newSpecies.toString());
    > }
    >
    >
    > Helper.convertOldSpeciesToNewSpecies(speciesOne, speciesTwo);
    >
    > Above calling, if the condition fits BLOCK B, result is correct
    > (speciesTwo gets the values it should get from inside the method).
    >
    > But if the condition fits BLOCK A, speciesTwo does NOT get the content
    > of speciesOne. The printing inside the method shows that newSpecies has
    > got the correct content (same as speciesOne).
    >
    > What is the problem? Thank you very much.
    >
    > For my practical reason, I do not want to change the method to
    >
    > public Species getNewSpecies(Species oldSpecies){..}


    The reference itself is passed by value. newSpecies is a reference
    holder, not an actual reference.

    --
    Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
    Daniel Pitts, Nov 7, 2007
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. E11
    Replies:
    1
    Views:
    4,720
    Thomas Weidenfeller
    Oct 12, 2005
  2. Howard
    Replies:
    2
    Views:
    366
    Michiel Salters
    Jul 4, 2003
  3. Rolf Magnus
    Replies:
    1
    Views:
    319
    ding feng
    Jul 4, 2003
  4. Jason
    Replies:
    2
    Views:
    495
    Jonathan Mcdougall
    May 13, 2006
  5. Juha Nieminen
    Replies:
    1
    Views:
    275
    Juha Nieminen
    Mar 2, 2009
Loading...

Share This Page