CMSC 202 Java Classes and Object 2 nd

CMSC 202 Java Classes and Object 2 nd Lecture Aug 6, 2007

Stack and Heap • When your program is running, some memory is used to store local variables. This memory is known as the stack. • We can use a table to represent variables stored on the stack Var Value x 42 y 3. 7 • The rest of memory is known as the heap and is used for dynamically allocated “stuff” (recall using malloc( ) in C) Aug 6, 2007 2

Main Memory The stack grows and shrinks as needed (why? ) The used part of the heap (“allocated”) also grows and shrinks. Some of the heap is unused (“free”) Stack Aug 6, 2007 Free Heap Used Heap 3

Object Creation Consider this code that creates two strings String s 1, s 2; s 1 = new String( “abc” ); s 2 = “abc” ; Note: Because Strings are very common, using new when creating String objects is optional. Where are these variables and object located in memory? Why do we care? Aug 6, 2007 4

Objects in Memory The statement String s 1, s 2; creates two local variables on the stack. The statements s 1 = new String( “abc” ); s 2 = “abc”; create objects on the heap. s 1 and s 2 contain the memory addresses of these objects giving us the picture of memory shown below. s 1 and s 2 are called reference variables. Reference variables which do not contain the memory address of any object contain the special value null Stack Heap s 1 s 2 Aug 6, 2007 abc 5

Why We Care (1 of 4) Given the previous code String s 1, s 2; s 1 = new String( “abc” ); s 2 = “abc”; and corresponding picture of memory consider the expression s 1 == s 2 Stack Heap s 1 s 2 abc Recall that s 1 and s 2 contain the addresses of their respective String objects. Since the String objects have different addresses on the heap, s 1 == s 2 is false. The == operator determines if two reference variables refer to the same object. So how do we compare Strings for equality? Strings (and other objects) implement a method named equals. To check if two Strings are the same, use the expression s 1. equals( s 2 ); . Aug 6, 2007 6

Why We Care (2 of 4) On the other hand, consider this code and corresponding picture of memory String s 1 = “abc”; String s 2 = s 1; Stack Heap s 1 s 2 abc s 1 and s 2 are ALIASed Now s 1 and s 2 refer to the same String object. This is known as ALIASING, is often unintentional, and can be dangerous. If your intent is for s 2 to be a copy of s 1, then the correct code is String s 2 = new String( s 1 ); Aug 6, 2007 7

Why We Care (3 of 4) Consider this code and the changing picture of memory String s 1 = “abc”; s 1 = “xyz”; S 1 = “Hello”; Stack Heap // line 1 // line 2 // line 3 Stack Heap Hello s 1 abc After line 1 Aug 6, 2007 s 1 abc After line 2 xyz s 1 abc xyz After line 3 8

Why We Care (4 of 4) • Garbage collection As the diagram shows, after line 3 is executed no variable refers to the String objects which contain “abc” or “xyz”. Stack Heap Hello s 1 abc xyz After line 3 In C/C++, we’d consider this a “memory leak”. In C/C++ it’s the programmer’s responsibility to return dynamically allocated memory back to the free heap. (recall using malloc and free in C? ) Not so in Java! Java has a built-in “garbage collector”. From time to time Java detects objects has been “orphaned” because no reference variable refers to them. The garbage collector automatically returns the memory for those objects to the free heap. Aug 6, 2007 9

Java expects certain methods to be implemented in virtually all class because some of the Java standard library functions assume they are defined. equals is one such method. This method compares two objects of the same class to see if they satisfy the intuitive definition of “being equal”. equals returns a Boolean value. Recall that you cannot use == to determine object equality. In general, the method definition of equals is public boolean equals( Class. Name Parameter. Name) Aug 6, 2007 10

equals for Date 1 Here’s an implementation of equals for our Date 1 class. Two Date 1 objects are equal if and only if they have identical month, day, and year public boolean equals( Date 1 other. Date) { This is the equals method for the String class return month. equals(other. Date. month) && day == other. Date. day && year == other. Date. year; } == okay here because day and year are ints Use == with primitive types, NOT with objects Aug 6, 2007 11

to. String While we’re on the subject, another method that Java assumes we have defined is to. String. • The purpose of the to. String method is to return a String value that represents the data in the object public String to. String() Aug 6, 2007 12

to. String for Date 1 Here’s a possible implementation of the to. String method for Date 1. You’re free to return any meaningful string such as “January 23, 1982” or “ 23 January 1982” public String to. String( ) { return month + “ “ + day + “, “ + year; } Aug 6, 2007 13

OOP Techniques We’ve seen how creating classes allows to combine the data and operations into a single entity. This technique is known as encapsulation and is a key part of OOP. Another, even more important technique in OOP is information hiding. This means separating the description of how to use the class from the details of the class implementation. Information hiding is also known as abstraction. Abstracting something means discarding some of the details. Aug 6, 2007 14

Information Hiding Why is information hiding (abstraction) a good thing? Using information hiding means that the programmer that uses your class does not need to know how the class is implemented, only how to use it. This keeps the information the programmer needs to a minimum. Just as important, if the users of your class don’t know how it’s implemented, you can change the implementation with no impact on those who use your class. Aug 6, 2007 15

Date 2 Class In this new class, the instance variable have been labeled private public class Date 2 { private String month; private int day; private int year; public void print( ) { System. out. println(month + “ “ + day + “ “ + year); } // set. Date and month. String included } Aug 6, 2007 16

Visibility Modifiers In our Date 1 class, the instance variables were labeled as public. As we saw in Date 1 Demo, there were no restrictions on how these variables could be used. In Date 2, we changed the visibility modifier from public to private. Private instance variables (and methods) are only accessible within their class. So code like this produces compiler errors. public class Date 2 Demo { public static void main( String[ ] args ) { Date 2 my. Date = new Date 2( ); my. Date. month = “July”; my. Date. day = 4; my. Date. year = 1950; // compiler error my. Date. set. Date( 7, 4, 1950); my. Date. print( ); // OK – why? } } Aug 6, 2007 17

Private Instance Variable It’s good programming practice to label all instance variables as private. Doing so means that the class has complete control over how/when/if the instance variables are changed. But if the instance variables are private, how does the class user access or modify them? IF the class implementer wants to allow the class user the privilege of accessing or modifying private instance variables, the implementer provides public methods known as accessors and mutators. These methods give the class user indirect access to the instance variables. The degree of access is still controlled by the class implementer. Aug 6, 2007 18

Accessors & Mutator An accessor is a method whose purpose is to retrieve the value of a (private) instance variable. It’s conventional to start the name of an accessor method with get. A mutator is a method that allows you to change the value of an instance variable. It’s conventional to start the name of an mutator with set. Aug 6, 2007 19

More Accessors and Mutators Question: Don’t the use of accessors and mutators defeat the purpose of making the instance variable private? Answer: No. 1. The class implementer decides which instance variables will have accessors. 2. Mutators can validate the new value of the instance variable and decide whether or not to actually make the requested change. Aug 6, 2007 20

New Class Model The use of private instance variables, accessors, and mutators gives us a better class model as shown in the diagram below. Aug 6, 2007 21

Encapsulation Aug 6, 2007 Copyright © 2008 Pearson Addison-Wesley. All rights reserved 22

Date 2 Accessor & Mutator public class Date 2 { private String month; private int day; // 1 - 31 private int year; // 4 -digit year // accessors return the value of private data public int get. Day ( ) { return day; } // mutators can validate the new value public boolean set. Year(int new. Year ) { if (new. Year < 1000 || new. Year > 9999) { // this is an invalid year return false; } else { year = new. Year; return true; } // rest of class definition follows } Aug 6, 2007 23

Other Methods and Comments Classes can provide many methods (besides accessors and mutators) that perform a variety of behaviors. Clear communication with the class user is of paramount importance so that he can use the appropriate method and use class methods properly. One important way of communicating with the class user is through the use of comments about each method. Two important types of method comments are known as pre-conditions and post-conditions. Aug 6, 2007 24

Pre- and Post-Condition A pre-condition states what is assumed to be true when a method is called. If any pre-condition is not met, the method cannot correctly perform its function. A post-condition describes the effect of the method. It states what will after the method executes (assuming all preconditions are met). Aug 6, 2007 25

A simple example Recall the print method from Date 2 that outputs the month string, day, and year to the screen. The print method might look something like this /* Pre. Condition: all instance variables of the calling object have a meaningful value Post. Condition: The calling object has been written to the screen in the format <month string> <day>, <year> */ public void print( ) { // code here } Aug 6, 2007 26

Another common example Very often the pre-condition specifies the limits of the parameters and the postcondition says something about the return value /* Pre-condition: 1 <= month <= 12 1 <= day <= 31 and appropriate for the month 1000 <= year <= 9999 Post-Condition: The month, day, and year of the calling object have been set to the parameter values. Return true if the calling object has been changed Returns false otherwise */ public boolean set. Date( int month, int day, int year) { // code here } Aug 6, 2007 27

What’s in a name? Not suprisingly, many different classes can all define a method with the same name (e. g. equals, to. String). Java can determine which method to call based on the type of the calling object. A little more suprising, however, is that two or more methods in the same class may have the same name. This is known as method overloading. Aug 6, 2007 28

Overloaded set. Date In our Date 2 class, we introduced the set. Date method public boolean set. Date( int month, int day, int year) But suppose we wanted to change only the day and year? We can define another method named set. Date like this public boolean set. Date( int day, int year) (after all, set. Date is a good descriptive name for what this method does) Aug 6, 2007 29

Date 3 Class with overloaded set. Data method public class Date 3 { private String month; private int day; private int year; // 1 - 31 // 4 digits public boolean set. Date( int new. Month, int new. Day, int new. Year) { // code here } public boolean set. Date( int new. Day, int new. Year ); { // code here, doesn’t change month } // print(), month. String( ), set. Year( ) follow } Aug 6, 2007 30

Date 3 Demo public class Date 3 Demo { public static void main (String[ ] args) { Date 3 my. Date = new Date 3( ); my. Date. set. Date( 1, 23, 1982 ); my. Date. print( ); my. Date. set. Date( 4, 1999 ); my. Date. print( ); } } How does Java know which set. Date to call? Aug 6, 2007 31

Method Signature In Java (and other OO languages), a method is uniquely identified by its name and its parameter list (parameter types and their order). public boolean Aug 6, 2007 set. Date( int new. Month, int new. Day, int new. Year) String new. Month, int new. Day, int new. Year) int new. Day, String new. Month) 32

Too much of a good thing Automatic type promotion and overloading can sometimes interact in ways that confuse the compiler. Consider this simple example public class X {. . . public void print. Average ( int a, double b) //version 1. . . public void print. Average ( double a, int b) //version 2 } And then consider this code snippet my. X = new X( ); my. X. print. Average( 5, 7 ); The Java compiler can’t decide whether to promote 7 to 7. 0 and call the first version of print. Average or to promote 5 to 5. 0 and call the second. The Java compiler is confused and will issue an error stating that the method invocation of my. X. print. Average is ambiguous Aug 6, 2007 33
- Slides: 33