|
home—info—exams—lectures—labs—hws
Recipe—Laws—lies—syntax—java.lang docs—java.util docs
Consider the following code:
int myFavoriteInt = 5; int yourFavoriteInt = 3*myFavoriteInt; (yourFavoriteInt == 15) // Will be true. myFavoriteInt = 7; // re-assigning to a variable! (yourFavoriteInt == 15) // Will be true. Math.Sqrt(yourFavoriteInt); // Doesn't change the value of yourFavoriteInt. /* ...more code which never assigns to "yourFavoriteInt"... */ (yourFavoriteInt == 15) // Will be true. |
We have already seen the assignment statement in the context
of initializing a local variable:
assignment-statement ::=
name = expression;
The semantics of the assignment statement are straightforward:
But compare with:
Dog myFavoriteDog = new Dog(); Dog yourFavoriteDog = myFavoriteDog; /* ...code which never *assigns* to "yourFavoriteDog", and moreover, never even *mentions* it. */ (myFavoriteDog == yourFavoriteDog) // Will be true. (yourFavoriteDog.getAge() == 0) // Might be false?!? |
But that doesn't mean that variables-holding-object-references (my,yourFavoriteDog) work differently than variables-holding-primitive-values (my,yourFavoriteInt). In fact, the variables work exactly the same: The value of myFavoriteDog never changed -- it is still a reference to the same dog. Agreed, the state of the Dog has been modified over time, but it's still the same Dog!.
So: you can't change the value of a variable without assigning to it, whether it's a primitive type or an object reference. 2 But, the contents of an object might change, even if your variable which references the object isn't explicitly mentioned in the code.
Is it a mistake, to allow myFavoriteDog and yourFavoriteDog to be two different ways of referring to the exact same Dog? Well, what happens if your favorite dog starts meowing? Well then, so does my favorite dog! So it's appropriate that changing the dog's sound is independent of how you and I each refer to that same dog.
Similarly, in the program for the registrar's office, there might be only one Student object corresponding to you, but several different variables which all refer to you. Your Dorm has a list of students which will include a reference to you; the Registrar has a list of all-students, as well as a list of honor-students and a list of students-with-outstanding-fines; you might be on all of these lists, or perhaps only one!
I had to apply for a university library card, and they had me fill out yet-another-form, with my phone number etc.. It turns out, that the library-program doesn't use the objects made by the Registrar's computer; I had to fill out a separate card (and re-list my name, phone-number, etc.). If I ever change my phone number, I'll need to tell both the library and the registrar to change it. This is poor data representation; there should be a single instance of (the object representing) me which all the different functions access.
On the other hand, for social reasons, perhaps it's good not to have a single central object with all the information:
The drawback of a lack of centralized database is that a criminal might be wanted by the police, yet still able to apply for parking permits and credit cards because there is no central database. (Or even, I might be wanted by the FBI, and yet when I'm pulled over by a local sherrif for speeding, the FBI information may not be shared with other systems, and I go free.) The costs and benefits of implementing the data the “correct” way (from a programmer's point of view) must be weighed with social realities.
int x = 16.0; Math.sqrt(x) x |
Note that while the parameter itself cannot be changed, the fields of that parameter can be. Assigning to the parameters doesn't actually modify what value was passed in:
void addSevenTo( int n ) { n = n+7; } // An utterly useless method. int addSevenTo_v2( int n ) { n = n+7; // Still bad practice, assigning to a parameter. return n; // But does give the correct answer. } int addSevenTo_v3( int n ) { return n+7; } // Acceptable style. int zz = 5; addSevenTo(zz); // zz is still 5. addSevenTo(zz+3); // zz+3 is still 8. addSevenTo(19); // 19 is still 19. addSevenTo_v2(zz) // returns 12; zz is still 5. addSevenTo_v2(zz+3) // returns 15; zz+3 is still 8. addSevenTo_v2(19) // returns 26; 19 is still 19. |
Dog d1 = new Dog(); Dog d2 = new Dog(); d1.ageOneYear(); Dog bestDog = d1; d1.setSound( "meow?" ); d1.swapSoundsWith(d2); // Whatever this method does, ... (d1 == bestDog) // ... this line MUST be true, even if d1's sound and age have both changed. |
/** Exchange the sounds of this dog and another dog. * @param other The Dog to exchange sounds with. */ void swapSoundsWith( Dog other ) { } |
We say: “Java always passes arguments by value”: it takes the actual argument's value, and uses (a copy of) that value to initalize the parameter. The thing to realize is that (in java) “references are values”.
Some languages allow something different: they let you “pass arguments by reference”, a special language-feature that would let you write something like swapInts(int,int). However, this has fallen out of favor recently, and is commonly viewed as something which can add obscure bugs without really giving the programmer more power. Just write methods which return a (reference to) the new items, and assign your variables explicitly.
1By the way, notice that Java variables work differently than spreadsheet cells: in a spreadsheet, if Y1 = 3 * M1, then any changes to M1 do cause Y1 to change. Java variables are not so sophisticated. But there are some programming languages for the web which do use such “reactive” variables. ↩
2Really, the truth is that assignment to the field of an object, (like this.age = 3) is very different than assignment to a variable (like n = 3). In fact, some languages refuse to use = for both of these situations: in Lisp, for example, set! is used to assign to variables, and set-Dog-age! is used to assign to the age field of a Dog. ↩
3 Although perhaps, maybe it should better be a method of MadScientist, with void swapDogsSounds( Dog a, Dog b ). ↩
home—info—exams—lectures—labs—hws
Recipe—Laws—lies—syntax—java.lang docs—java.util docs
©2007, Ian Barland, Radford University Last modified 2007.Aug.27 (Mon) |
Please mail any suggestions (incl. typos, broken links) to ibarlandradford.edu |