JMU JMU - Department of Computer Science
Help Tools
Lab: Experimenting with Reference Types


Instructions: Answer the following questions one at a time. After answering each question, check your answer (by clicking on the check-mark icon if it is available) before proceeding to the next question.

1. Getting Started: This part of the lab will get you started.
  1. Read the documentation for the SavingsAccount class Click here for the documentation. .
  2. What are the behaviors of SavingsAccount objects?


    void deposit(double)
    double getBalance()
    String getID()
    void withdraw(double)
    
    Expand
  3. Given these behaviors, at a minimum, what properties/attributes do SavingsAccount objects most likely have?


    An ID and a balance.
    Expand
  4. What does it mean when we say that an object is immutable?


    It means that the properties/attributes of the object can't be changed after it is constructed.
    Expand
  5. Are String java.lang.String objects mutable or immutable?


    They are immutable. (As it says in the documentation, "their values cannot be changed after they are created".)
    Expand
  6. What is printed by the following fragment?
     
           String       university;
    
           university = "jmu";
           university.toUpperCase();
           System.out.println(university);
        


    jmu
    
    Expand
  7. Why?


    String objects are immutable. So, a call to toUpperString() can't change the object that is referred to by jmu.
    Expand
  8. Are SavingsAccount objects mutable or immutable?


    Given that both the deposit() and withdraw() methods must change the balance to be useful, they are mutable.
    Expand
  9. What do you need to pass the constructor of the SavingsAccount class?


    A String containing the ID.
    Expand
  10. Is there a way to change the ID of a SavingsAccount?


    There doesn't appear to be.
    Expand
  11. Are double and int primitive types or reference types?


    They are both primitive types. (They are easily identified because, by convention, they start with a lower case letter.)
    Expand
  12. What does it mean when we say that a type is a primitive type?


    It means that variables of that type contain a primitive value. For example, if we assign 2.0 to the double variable price, then the memory location associated with price contains the value 2.0.
    Expand
  13. Is String a primitive type or a reference type?


    A reference type (because it is a class type). (Class types are easily identifier because, by convention, they start with an uppercase letter.)
    Expand
  14. Is SavingsAccount a primitive type or a reference type?


    It, too, is a reference type (because it is a class type)
    Expand
  15. What does it mean when we say that class types in Java are reference types?


    It means that object variables contain the "address" of the actual object. For example, if we construct a SavingsAccount and assign the result to a variable named barney, then the memory location associated with barney contains the "address" of the object, not the actual object itself.
    Expand
2. Working with Reference Types: This part of the lab will help you better understand reference types. You should build a model of memory to help you answer these questions.

Be careful! When a question begins with "What is printed by" you are starting a fragment from scratch. When a question begins with "Add the following" you are continuing an existing fragment.

  1. What is printed by the following fragment?
     
           String       university;
    
           university = "jmu";
           System.out.prinln(university == "jmu");
        


    true
    
    Expand
  2. Why?


    Because the reference to the String literal "jmu" is assigned to the variable university. Hence, they both refer to the same thing (i.e., contain the same address).
    Expand
  3. What is printed by the following fragment?
     
           String       university;
    
           university = "jmu";
           university = university.toUpperCase();
           System.out.println(university);
        


    JMU
    
    Expand
  4. Why?


    The toUpperString() method in the String class constructs a new String object that contains the uppercase versions of all of the characters in the calling String and returns a reference to that String. That reference is then assigned to the variable named university.
    Expand
  5. What is printed by the following fragment?
     
           String       university;
    
           university = "jmu";
           System.out.prinln(university.toUpperCase() == "JMU");
        


    false
    
    Expand
  6. Why?


    Because the reference to the String literal "JMU" is not the same as the reference to the String object that was constructed in the toUpperCase() method.
    Expand
  7. What is printed by the following fragment?
     
           SavingsAccount       wilma;
    
           wilma = new SavingsAccount("WF");
           System.out.printf("%2s\n", wilma.getID());
        


    WF
    
    Expand
  8. Add the following to the end of the above fragment.
     
           System.out.printf("%2s\n", wilma.getID() == "WF");
        

    What is printed by the additional statements?


    false
    
    Expand
  9. Why?


    String is a reference type. So String variables actually contain the address of the object. In this case, the address of the String literal"WF" is not the same as the address of the String that is returned by wilma.getID() because the constructor makes a deep copy of the String it is passed.
    Expand
  10. Add the following to the end of the above fragment.
     
           System.out.printf("%2s\n", wilma.getID().equals("WF"));
        

    What is printed by the additional statements?


    true
    
    Expand
  11. Why?


    Because the equals() method in the String class compares the attributes (i.e., the characters) of the String objects, not their addresses. In this case, they both String objects contain the characters 'W' and 'F'.
    Expand
  12. What is printed by the following fragment?
           SavingsAccount       wilma;
    
           wilma = new SavingsAccount("WF");
           wilma.deposit(100.00);
           System.out.printf("%2s  % 8.2f\n", wilma.getID(), wilma.getBalance());
          


    WF    100.00
    
    Expand
  13. Add the following to the end of the above fragment.
     
           wilma.deposit(200.00);
           wilma.withdraw(50.00);
           System.out.printf("%2s  % 8.2f\n", wilma.getID(), wilma.getBalance());
        

    What is printed by the additional statements?


    WF    250.00
    
    Expand
  14. Why?


    Because the attributes of the SavingsAccount object referred to by wilma were changed by the two method calls. In particular, first 200 was added to the balance and then 50 was subtracted from the balance (which was initially 100).
    Expand
  15. Add the following to the end of the above fragment.
     
           wilma = new SavingsAccount("BR");
           wilma.deposit(50.00);
           System.out.printf("%2s  % 8.2f\n", wilma.getID(), wilma.getBalance());
        

    What is printed by the additional statements?


    BR     50.00
    
    Expand
  16. Why? In other words, why has the balance of the wilma object changed?


    Because a new SavingsAccount object was constructed and its address was assigned to wilma. In other words, wilma refers to a completely different object. So, now, all calls to methods that belong to wilma operate on this new object.
    Expand
  17. Suppose you wanted to now get information about the SavingsAccount object with the ID of "WF". How would you do it, or would it be impossible?


    It would be impossible because we don't have a variable that refers to that object any longer. In other words, we no longer have its address. At some point, that object will be garbage collected.
    Expand
  18. What is printed by the following fragment?
     
           SavingsAccount       wilma;
           SavingsAccount       oldWilma;       
    
           wilma = new SavingsAccount("WF");
           wilma.deposit(100.00);
           System.out.printf("wilma:    %2s  % 8.2f\n", wilma.getID(), wilma.getBalance());
        


    wilma:    WF    100.00
    
    Expand
  19. Add the following to the end of the above fragment.
           oldWilma = wilma;
           System.out.printf("oldWilma: %2s  % 8.2f\n", oldWilma.getID(), oldWilma.getBalance());
        

    What is printed by the additional statements?


    oldWilma: WF    100.00
    
    Expand
  20. Why?


    When wilma is assigned to oldWilma what actually happens is that the address in wilma is assigned to oldWilma. Hence, the two variables contain the address of (i.e., refer to) the same object. (They are said to be aliases for the same object.)
    Expand
  21. Add the following to the end of the above fragment.
     
           wilma.deposit(100);
           System.out.printf("wilma:    %2s  % 8.2f\n", wilma.getID(), wilma.getBalance());
        

    What is printed by the additional statements?


    wilma:    WF    200.00
    
    Expand
  22. Why?


    The balance property of the object referred to by wilma was changed by the call to deposit().
    Expand
  23. Add the following to the end of the above fragment.
     
           System.out.printf("oldWilma: %2s  % 8.2f\n", oldWilma.getID(), oldWilma.getBalance());
        

    What is printed by the additional statements?


    oldWilma: WF    200.00
    
    Expand
  24. Why?


    Again, oldWilma and wilma are aliases for the same object.
    Expand
  25. Add the following to the end of the above fragment.
     
           oldWilma.deposit(100);
           System.out.printf("wilma:    %2s  % 8.2f\n", wilma.getID(), wilma.getBalance());
           System.out.printf("oldWilma: %2s  % 8.2f\n", oldWilma.getID(), oldWilma.getBalance());
        

    What is printed by the additional statements?


    wilma:    WF    300.00
    oldWilma: WF    300.00
    
    Expand
  26. Why?


    How many times to you want me to say it? oldWilma and wilma are aliases for the same object.
    Expand
  27. What is printed by the following fragment?
     
           SavingsAccount       wilma;
           SavingsAccount       oldWilma;       
    
           wilma = new SavingsAccount("WF");
           wilma.deposit(100.00);
           oldWilma = wilma;       
           System.out.printf("wilma:    %2s  % 8.2f\n", wilma.getID(), wilma.getBalance());
           System.out.printf("oldWilma: %2s  % 8.2f\n", oldWilma.getID(), oldWilma.getBalance());
        


    wilma:    WF    100.00
    oldWilma: WF    100.00
    
    Expand
  28. Add the following to the end of the above fragment.
     
           wilma = new SavingsAccount("BR");
           wilma.deposit(500.00);
           System.out.printf("wilma:    %2s  % 8.2f\n", wilma.getID(), wilma.getBalance());
           System.out.printf("oldWilma: %2s  % 8.2f\n", oldWilma.getID(), oldWilma.getBalance());
        

    What is printed by the additional statements?


    wilma:    BR    500.00
    oldWilma: WF    100.00
    
    Expand
  29. Why?


    oldWilma refers to the original SavingsAccount object (i.e., the one with the ID of "WF"). wilma now refers to the SavingsAccount object with the ID of "BR".
    Expand
  30. Add the following to the end of the above fragment.
     
           oldWilma.withdraw(100.00);
           System.out.printf("wilma:    %2s  % 8.2f\n", wilma.getID(), wilma.getBalance());
           System.out.printf("oldWilma: %2s  % 8.2f\n", oldWilma.getID(), oldWilma.getBalance());
        

    What is printed by the additional statements?


    wilma:    BR    500.00
    oldWilma: WF      0.00
    
    Expand
  31. Why?


    wilma continues to refer to the SavingsAccount object withe the ID of "BR", and it was not changed. oldWilma refers to the SavingsAccount object withe the ID of "WF", which had a balance of 100.00 before the call to withdraw() and so now has a balance of 0.00.
    Expand
  32. Add the following to the end of the above fragment.
     
           wilma = oldWilma;
           System.out.printf("wilma:    %2s  % 8.2f\n", wilma.getID(), wilma.getBalance());
           System.out.printf("oldWilma: %2s  % 8.2f\n", oldWilma.getID(), oldWilma.getBalance());
        

    What is printed by the additional statements?


    wilma:    WF      0.00
    oldWilma: WF      0.00
    
    Expand
  33. Why?


    Both wilma and oldWilma now refer to the SavingsAccount object with the ID of "WF".
    Expand
  34. Suppose you wanted to now get information about the SavingsAccount object with the ID of "BR". How would you do it, or would it be impossible?


    It would be impossible because we don't have a variable that refers to that object any longer. In other words, we no longer have its address. At some point, that object will be garbage collected.
    Expand
  35. Add the following to the end of the above fragment.
     
           wilma = null;
           System.out.printf("wilma:    %2s  % 8.2f\n", wilma.getID(), wilma.getBalance());
        

    What will happen when you execute the application?


    You will get a NullPointerException.
    
                                     
    Expand
  36. Why?


    Because the variable wilma no longer refers to an object of type SavingsAccount. So, you can't tell wilma to do anything anymore. When you invoke wilma.getBalance() you are telling null, which is not a reference to an object, to get it's balance, which it doesn't have.
    Expand
3. Reference Types and the final Modifier: This part of the lab will help you better understand reference types that are declared to be final. Some questions in this part of the lab use the following Range class (which has public attributes for convenience, not because it is good practice).

  public class Range
  {
      public int    max, min;
  }
  

  1. Which of the following statements won't compile (if any)?
     
            final String   theBestUniversity;
            
            theBestUniversity = "JMU";
            theBestUniversity = "UVA";
        


    The last statement won't compile.
    Expand
  2. Why?


    Because the variable theBestUniversity has already been initialized and, since it has been declared to be final, can't be "re-assigned".

    Note that the answer to this question has nothing to do with the fact that String objects are immutable.

    Expand
  3. Which of the following statements (in a class other than Range) won't compile (if any)?
     
                 Range        cool  = new Range();
           final Range        warm = new Range();
        


    They will both compile.
    Expand
  4. Which of the following statements (in a class other than Range) won't compile (if any)?
     
                 Range        cool  = new Range();
           final Range        warm = new Range();
    
           cool = new Range();
           warm = new Range();       
        


    The last line won't compile.
    Expand
  5. Why?


    Again, because you can't assign a value to a final variable that has already been initialized.
    Expand
  6. Which of the following statements (in a class other than Range) won't compile (if any)?
     
                 Range        cool  = new Range();
           final Range        warm = new Range();
    
           cool.min = 41;
           cool.max = 55;
           warm.min = 56;
           warm.max = 65;
        


    They will all compile.

    This might surprise you at first because warm is declared to be final. However, if you think about it, you'll realize that warm (which is a reference) is not changing.

    Expand
  7. Which of the following statements (in a class other than SavingsAccount) won't compile (if any)?
     
            final SavingsAccount   betty = new SavingsAccount("BR");
            betty.deposit(100.00);
        


    They will both compile.
    Expand
  8. Why?


    Because betty, which is a reference, is not being changed.

    Note that the answer to this question has nothing to do with the fact that SavingsAccount objects are mutable (except to the extent that it means that there is a deposit() method).

    Expand
4. Passing Reference Types: This part of the lab will help you understand what happens when reference types (e.g., objects) are passed. If we have not yet discussed parameter passing in lecture then you should come back and answer these questions after we have done so. You should build a model of memory to help you answer these questions.

Be careful! When a question begins with "What is printed by" you are starting a fragment from scratch. When a question begins with "Add the following" you are continuing an existing fragment.

  1. Does Java pass parameters by value or by reference?


    By value.
    Expand
  2. What does it mean when we say that a parameter is passed by value?


    It means that a copy of the parameter is made and the copy is used in the method.
    Expand
  3. What is printed by the following application?
     
    public class Driver
    {
        public static void main(String[] args)
        {
           SavingsAccount   wilma;
    
           wilma = new SavingsAccount("WF");       
           wilma.deposit(100.00);
           System.out.printf("Before process(): %2s  % 8.2f\n", 
                             wilma.getID(), wilma.getBalance());
           process(wilma);       
           System.out.printf("After process():  %2s  % 8.2f\n", 
                             wilma.getID(), wilma.getBalance());
        }
    
        public static void process(SavingsAccount account)
        {
           System.out.printf("In process():     %2s  % 8.2f\n", 
                             account.getID(), account.getBalance());
        }
    }
        


    Before process(): WF    100.00
    In process():     WF    100.00
    After process():  WF    100.00
    
    Expand
  4. Add the following to the top of the process() method (i.e., before the call to printf() in the process() method).
     
           account.deposit(50.00);       
        

    What is printed now?


    Before process(): WF    100.00
    In process():     WF    150.00
    After process():  WF    150.00
    
    Expand
  5. Why is a different balance printed in the "Before" line and the "After" line (given that wilma still refers to the same object and a copy of the reference, not the original reference, was passed).


    wilma is, indeed, a reference type that is passed by value. So, account is, indeed, a copy of the address in wilma. This means that account is an alias for wilma. That is, account refers to the same object as wilma. Hence, when the object referred to be account is told to make a deposit, it is the same object that is referred to by wilma.
    Expand
  6. Change the body of the process() method to the following. (In other words, delete the existing body and replace it with the following.)
     
           account = new SavingsAccount("BR");
           account.deposit(200);       
           System.out.printf("In process():     %2s  % 8.2f\n", 
                             account.getID(), account.getBalance());
        

    What is printed now?


    Before process(): WF    100.00
    In process():     BR    200.00
    After process():  WF    100.00
    
    Expand
  7. Why is the same thing printed in the "Before" line and the "After" line?


    wilma is a reference type that is passed by value. This means that account is a copy of the address in wilma. When a new SavingsAccount is constructed in the process() method, its address is assigned to account. This doesn't change the object referred to by wilma. In addition, account no longer is a copy of the address in wilma. So, when the object referred to be account is told to make a deposit, it is a different object than the one referred to by wilma.
    Expand
5. Don't Believe the Answers Above?: Though it is not necessary that you do so, if you want to run any of the examples (perhaps because you have doubts about the answers), you will need to download either the SavingsAccount.class file or the lab.jar file (by right-clicking on the link) and add it to your project. (See the course "Help" page on the IDE for more information.)

Copyright 2022