Thursday, January 13, 2011

Learning Objects for Methods in Java

Learning Objects for Methods

Concept Methods are the simplest construct for abstraction in Java. A method starts with a declaration that defines its signature: the name of the method, the number and types of the formal parameters and the return type. The body of the method consists of local variable declarations and of statements. A method is called or invoked by writing the name of the method followed by a list of values, called actual parameters, one for each formal parameter. A method can return a value or it can be declared as void if no value is returned.
These source code of these learning objects can be found in method.zip.
TABLE 1
LOTopicJava Files (.java)Prerequisites
"A void method"A void methodMethod01 
"A method returning a value"A method returning a valueMethod02 
"Calling one method from another"Calling one method from anotherMethod031, 2
"Recursion"RecursionMethod042
"Calling methods on an object"Calling methods on an objectMethod052, *
"Calling a method on the same object"Calling a method on the same objectMethod065, *
"Objects as parameters"Objects as parametersMethod075, *
"Returning objects"Returning objectsMethod087, *
"Returning locally instantiated objects"Returning locally instantiated objectsMethod098, *
* This LO assumes knowledge of the declaration of classes and the instantiation of objects.

A void method

Concept When a method that is declared void is called, it allocates memory for its parameters and local variables, executes its statements and then returns. The call is a statement constructed from the name of the method followed by a list of actual parameters.
Program: Method01.java
// Learning Object Method01
//    void methods
public class Method01 {
    static void printMax(int a, int b) {
        int max;
        if (a > b)
            max = a;
        else
            max = b;
        System.out.println(max);
    }
 
    public static void main(/*String[] args*/) {
        int x = 10, y = 20;
        printMax(x, y);
        Method01.printMax(10, y);
    }
}
The program computes the maximum of two integer values.
  • The variables x and y are allocated and initialized.
  • The method is called with the values of the actual parameters x and y.
  • Memory is allocated for the formal parameters of the method and the local variables. This is called an activation record and is displayed by Jeliot in the upper left hand part of the screen labeled Method Area. The new activation record hides the previous ones which are no longer accessible.
  • The actual parameters are used to initialize the formal parameters in the activation record.
  • The local variable max is allocated within the activation record.
  • The statements of the method are executed.
  • After the last statement has been executed, the method returns and the activation record is deallocated.
  • Execution continues with the statement after the method call. Here, the method is called again, this time with an integer literal as an actual parameter instead of a variable.
Note: In a call to a static method, the name of the class in which it is defined can be given as in the second call. Since the method is defined in the same class as the call, the class name need not be given, as shown in the first call.
Exercise Trace the execution of a call of the following method and explain why it doesn't swap the values of the actual parameters.
void swap(int a, int b) {
 int temp = a;
 a = b;
 b = temp;
}
Can you write a method to swap two integer values?

A method returning a value

Concept When a method that is declared with a return type is called, it allocates memory for its parameters and local variables, executes its statements and then returns a value of the type. The call is a statement constructed from the name of the method followed by a list of actual parameters; the call is an expression and can appear wherever an expression is allowed.
Program: Method02.java
// Learning Object Method02
//    methods returning a value
public class Method02 {
    static int maximum(int a, int b) {
        if (a > b)
            return a;
        else
            return b;
    }
 
    public static void main(/*String[] args*/) {
        int x = 10, y = 20;
        int max;
        max = maximum(x, y);
        System.out.println(max);
    }
}
  • The variables x and y are allocated and initialized; the variable max is allocated but not initialized.
  • An assignment statement is executed: the expression on the right hand side is a method call including the values of the actual parameters x and y.
  • Memory is allocated for the formal parameters of the method and the local variables. This is called an activation record and is displayed by Jeliot in the upper left hand part of the screen labeled Method Area. The new activation record hides the previous ones which are no longer accessible.
  • The actual parameters are used to initialize the formal parameters in the activation record.
  • The statements of the method are executed.
  • When the statement return b is executed, the value of b is used for the value to be returned.
  • The method returns and the activation record is deallocated.
  • The value returned becomes the value of the expression assigned to the variable max.
  • The value of max is printed.
Exercise Write the body of the main method as one statement.

Calling one method from another

Concept One method can call another, that is, when executing one method, any statement or expression call be a method call. A sequence of method calls results in a stack of activation records, where each method (except the last one that was called) is waiting for the method it called to return. There is no limit on the depth of method calls, except of course the amount of memory allocated to the program.
Note: The main method is a method like any other. The operating system can be considered as a program which calls the main method. This call has a single parameter: an array of strings containing the contents of the command line.
Program: Method03.java
// Learning Object Method03
//    calling a method from a method
public class Method03 {
    static int maximum(int a, int b) {
        if (a > b)
            return a;
        else
            return b;
    }
 
    static void printMax(int a, int b) {
        int max;
        max = Method03.maximum(a, b);
        System.out.println(max);
    }
 
    public static void main(/*String[] args*/) {
        printMax(10, 20);
    }
}
  • The main method calls the method printMax; the actual parameters are two integer literals.
  • The activation record for printMax is allocated, and the actual parameters are used to initialize the formal parameters a and b.
  • The variable max is allocated but not initialized.
  • The method maximum is called; the actual parameters are the values of a and b, which are the formal variables of method printMax.
  • An activation record is allocated for maximum. (There are now three activation in the stack.) The new activation record includes memory for the formal parameters a and b; note that these are new parameters not at all related to the formal parameters of the same names in the previous method printMax because those parameters are hidden.
  • The method maximum executes its body and returns a value. Just before it returns, select the tab Call Tree above the graphic display; the sequence of calls from main toprintMax and then maximum is displayed. Select Theater to return to the animated display.
  • When the method returns, its activation record is deallocated, uncovering the activation record of printMax.
  • The value returned is assigned to the variable max and printed.
  • When printMax completes its execution, its activation record is deallocated.
Note: In a call to a static method, the name of the class in which it is defined can be given as in the call to maximum. Since the method is defined in the same class as the call, the class name need not be given, as shown in the call to printMax.
Exercise Write a program to compute the maximum of six values using as few statements as possible.

Recursion

ConceptRecursion occurs when method calls itself. There is nothing at all mysterious about recursion! Each call simply creates a new activation record on the stack. However, to ensure that the recursive calls terminate, eventually, some call of the method should return without invoking itself once again.
Program: Method04.java
// Learning Object Method04
//    recursion
public class Method04 {
    static int factorial (int n) {
        if (n <= 1)
            return 1;
        else
            return n * factorial(n-1);
    }
 
    public static void main(/*String[] args*/) {
        System.out.println(factorial(5));
    }
}
The standard example of a recursive method is one that computes the factorial function:
n!=n·(n1)··2·1=n·(n1)!(1)
The recursion is terminated by defining n!=1 for n1.
  • The main method calls the method factorial with the actual parameter 5. This creates an activation record with the formal parameter n initialized to 5.
  • To compute the expression in the second return statement, the method factorial is called again, this time with the actual parameter equal to 51=4.
  • The sequence of recursive calls continues five times, each one allocating a new activation record with a new variable n.
  • Finally, factorial is called with actual parameter 1. This call creates a new activation record as usual, but does not cause factorial to be invoked again. Instead, the value 1 is returned and the activation record is deallocated. Just before the method returns, select the tab Call Tree above the graphic display; the sequence of calls from main to the sequence of recursive calls is displayed. Select Theater to return to the animated display.
  • The recursive sequence unfolds: each returned value is used to compute a new value to be returned by that call of factorial.
  • Finally, the value 120 is returned to the main method and printed.
Exercise Write a recursive method to compute the n'th Fibonacci number:
fib(0)=0,fib(1)=1,fib(n)=fib(n1)+fib(n2)forn>1.(2)
Exercise Write a more efficient nonrecursive method for the same function.

Calling methods on an object

Concept Nonstatic methods defined in a class must be invoked on an object of the class. A reference to the object becomes an implicit actual parameter that initializes a formal variable called this in the method. The variable this need not be explicitly mentioned when accessing fields of the object unless there is an ambiguity.
Program: Method05.java
// Learning Object Method05
//    calling methods on an object
class Song {
    int seconds;
 
    Song(int s) {
        seconds = s;
    }
 
    double computePrice(double pricePerSecond) {
       return seconds * pricePerSecond;
    }
}
 
public class Method05 {
    public static void main(/*String[] args*/) {
        Song song1 = new Song(164);
        Song song2 = new Song(103);
        double price1 = song1.computePrice(0.01);
        double price2 = song2.computePrice(0.02);
        System.out.println(price1);
        System.out.println(price2);
    }
}
This program computes the cost of a song as the product of its length in seconds and the price per second. A class Song is defined to encapsulate the field seconds and the methodcomputePrice.
  • Two objects of class Song are instantiated and references to them are assigned to the variables song1 and song2.
  • The method computePrice is called on the object referenced by song1. In Jeliot this is visualized by an arrow to the object placed in the Expression Evaluation Areafollowed by a period and the method name and parameters.
  • An activation record is allocated containing two formal parameters: this is initialized by the implicit reference and pricePerSecond is initialized from the actual parameter.
  • The reference in the parameter this is used to obtain the value of the field seconds. An expression is evaluated and its value returned.
  • The activation record is deallocated and the value returned is stored in the variable price1.
  • A second call to the method is executed in exactly the same way, except that it is called on the object referenced by song2.
  • The values of price1 and price2 are printed.
Exercise Modify the method so that the formal parameter is also named seconds. Yes, it can be done! (Hint: read the Concept paragraph above.)

Calling a method on the same object

Concept A nonstatic method defined in a class that is invoked on an object of the class can invoke another such method on the same object. The object for the second call is the same as the one on the first call, namely, the only referenced by this. There is no need to explicitly write this and the object may be accessed implicitly.
Program: Method06A.java
// Learning Object Method06A
//    calling a method on the same object
class Song {
    int seconds;
 
    Song(int s) {
        seconds = s;
    }
 
    boolean discount(int s) {
        return s > 300;
    }
 
    double computePrice(double pricePerSecond) {
        double price = seconds * pricePerSecond;
        if (discount(seconds))
            price = price * 0.9;
        return price;
    }
}
 
public class Method06A {
    public static void main(/*String[] args*/) {
        Song song1 = new Song(164);
        Song song2 = new Song(403);
        double price1 = song1.computePrice(0.01);
        double price2 = song2.computePrice(0.01);
        System.out.println(price1);
        System.out.println(price2);
    }
}
This program computes the cost of a song as the product of its length in seconds and the price per second. A discount is applied to “long” songs. A class Song is defined to encapsulate the field seconds and the methods computePrice and discount.
  • Two objects of class Song are instantiated and references to them are assigned to the variables song1 and song2.
  • The method computePrice is called on the object referenced by song1. In Jeliot this is visualized by an arrow to the object placed in the Expression Evaluation Areafollowed by a period and the method name and parameters.
  • An activation record is allocated containing two formal parameters: this is initialized by the implicit reference and pricePerSecond is initialized from the actual parameter.
  • The local variable price is declared and initialized by the expression calculated from the formal parameter pricePerSecond and the field of the object seconds that is implicitly accessed through this.
  • The method discount, declared in the same class, is invoked and returns a boolean value. A new activation is allocated for this method and deallocated when it terminates. The implicit actual parameter is this and it is used to initialize the implicit formal parameter this of the method discount.
  • The activation record for computePrice is deallocated and the value returned is stored in the variable price1.
  • A second call to the method is executed exactly the same way, except that it is called on the object referenced by song2.
  • The values of price1 and price2 are printed.
Exercise Modify the program so that discount does not use the explicit parameter s.
Program: Method06B.java
// Learning Object Method06B
//    calling a method on the same object
class Song {
    int seconds;
 
    Song(int s) {
        seconds = s;
    }
 
    static int level(int n) {
        return n * 100;
    }
 
    boolean discount(int s) {
        return s > level(3);
    }
 
    double computePrice(double pricePerSecond) {
        double price = seconds * pricePerSecond;
        if (discount(seconds))
            price = price * 0.9;
        return price;
    }
}
 
public class Method06B {
    public static void main(/* String[] args */) {
        Song song1 = new Song(164);
        Song song2 = new Song(403);
        double price1 = song1.computePrice(0.01);
        double price2 = song2.computePrice(0.01);
        System.out.println(price1);
        System.out.println(price2);
    }
}
Given a call to a method m2 within a method m1:
void m1() {
  m2();
}
it is impossible to tell from the call if m2 is being implicitly called on the same object or if it is a static method defined in the class.
  • This program is a modification of the previous one: instead of comparing s with 300 in the method discount, it is compared with the value returned by the method level. It is impossible to tell from the calls alone to discount and level that the first is a call on an object while the second is a call to a static method.
Exercise Modify the calls to discount and level so that it is immediately apparent which is definitely a call on an object and which is definitely a call to a static method.

Objects as parameters

Concept A reference to an object can be an actual parameter whose corresponding formal parameter is declared to be of the same class. As with all parameters, the value of actual parameter is used to initialize the formal parameter, but since it is a reference that is passed, the method that is called can access fields and methods of the object. This is calledreference semantics.
Program: Method07.java
// Learning Object Method07
//    objects as parameters
class Song {
    int seconds;
 
    Song(int s) {
        seconds = s;
    }
 
    double computePrice(double pricePerSecond) {
       return seconds * pricePerSecond;
    }
}
 
public class Method07 {
 
    static double getPrice(Song s, double ppS) {
        return s.computePrice(ppS);
    }
 
    public static void main(/*String[] args*/) {
        Song song1 = new Song(164);
        Song song2 = new Song(103);
        double price1 = getPrice(song1, 0.01);
        double price2 = getPrice(song2, 0.02);
        System.out.println(price1);
        System.out.println(price2);
    }
}
This program computes the cost of a song as the product of its length in seconds and the price per second. A class Song is defined to encapsulate the field seconds and the methodcomputePrice. The method getPrice in the main method receives an object of class Song as a parameter and calls computePrice.
  • Two objects of class Song are instantiated and references to them are assigned to the variables song1 and song2.
  • The method getPrice is called with two parameters: the first is a reference song1 to an object of class Song, while the second is a value of type double. The actual parameters are used to initialize the formal parameters; check that song1 and s reference the same object.
  • Since the formal parameter s receives a reference to an object of class Song (in this case song1), it can be used to call the method computePrice declared in the class.
  • The method returns a value that is assigned to price1.
  • A second call to the method is executed exactly the same way, except that the actual parameter is the reference contained in song2.
  • The values of price1 and price2 are printed.
Exercise Modify the program so that discount does not use the explicit parameter s.

Returning objects

Concept A return value can be a reference to an object.
Program: Method08.java
// Learning Object Method08
//    returning objects
class Song {
    int seconds;
 
    Song(int s) {
        seconds = s;
    }
 
    double computePrice(double pricePerSecond) {
       return seconds * pricePerSecond;
    }
}
 
public class Method08 {
 
    static Song longer(Song s1, Song s2) {
        if (s1.seconds > s2.seconds)
            return s1;
        else
            return s2;
    }
 
    public static void main(/*String[] args*/) {
        Song song1 = new Song(164);
        Song song2 = new Song(103);
        Song longerSong  = longer(song1, song2);
        double price2 = longerSong.computePrice(0.01);
        System.out.println(price2);
    }
}
This program computes the cost of a song as the product of its length in seconds and the price per second. A class Song is defined to encapsulate the field seconds and the methodcomputePrice. The method longer in the main method receives references to two objects of class Song as parameters and returns a reference to the one with the larger value of the field seconds.
  • Two objects of class Song are instantiated and references to them are assigned to the variables song1 and song2.
  • The method longer is called with two parameters that are references to objects of class Song. The actual parameters are used to initialize the formal parameters; check thatsong1 and s1 reference the same object, as do song2 and s2.
  • Since the formal parameters s1 and s2 receive references to objects of class Song, they can be used to access the fields seconds of each object.
  • The method returns the reference to the object whose field seconds has the larger value. The reference is assigned to the variable longerSong; check that this reference is to the same object as the reference in song1.
  • The reference in longerSong is used to call the method computePrice and the value returned is assigned to the variable price2.
  • The value price2 is printed.
Exercise Modify the program so that discount does not use the explicit parameter s.
Exercise Replace the last declaration and statements of the program by one declaration.
Exercise Write a method to swap two integer values.

Returning locally instantiated objects

Concept When a method terminates, its activation record is deallocated. However, if an object has been instantiated within the method, a reference to the object can be returned to the calling method.
Program: Method09.java
// Learning Object Method09
//    returning locally instantiated objects
class Song {
    int seconds;
 
    Song(int s) {
        seconds = s;
    }
 
    double computePrice(double pricePerSecond) {
       return seconds * pricePerSecond;
    }
}
 
public class Method09 {
 
    static Song doubleSong(Song s1) {
        Song d = new Song(s1.seconds*2);
        return d;
    }
 
    public static void main(/*String[] args*/) {
        Song song1 = new Song(164);
        Song longSong  = doubleSong(song1);
    }
}
This program computes the cost of a song as the product of its length in seconds and the price per second. A class Song is defined to encapsulate the field seconds and the methodcomputePrice. The method double in the main method receives a reference to an object of class Song as a parameter and returns a reference to an new object of class Songwhose field seconds is twice as large.
  • Two objects of class Song are instantiated and references to them are assigned to the variables song1 and song2.
  • The method doubleSong is called with an actual parameter that is a reference song1 to an object of class Song. The actual parameter is used to initialize the formal parameter; check that song1 and s1 reference the same object.
  • Within the method, the seconds field of the object referenced by s1 is used to instantiate a new object whose reference is assigned to the variable d of class Song.
  • The method returns the reference to the object contained in d; although d disappears when the activation record is deallocated, the object still exists as does the reference that is returned.
  • The returned reference is assigned to the variable longSong; check that song1 and longSong reference different objects!

No comments:

Post a Comment

Related Posts Plugin for WordPress, Blogger...

java

Popular java Topics