USER-CREATED  JAVA  METHODS

TOPICS


Top-Down Design and Java Methods.
Predifined Methods in Java
User-Defined Methods in Java

Value_returning Methods
Void Methods

Overloading Methods
Scope of Identifiers within a Class(Local, Global)
Value v.s Reference Semantics

Sample Programs:

Program #1: Java Program - value returning methods, overloading methods
Program #2: Java Program - value parameters

 

OUTLINE


1. Top-Down Design and Java Methods
 

·  Before starting to write a program, one should design first the algorithm. One method in designing algorithms - break down the task to be accomplished into few subtasks, decompose each of these subtasks into smaller subtasks, and so forth, till the subtasks become so small that they are trivial to implement in a programming language.

·  Such a method is called "top-down design." Sometimes it is also called "stepwise refinement" or "divide and conquer."

·  Advantages of top-down design:

·  Programs are easier to understand

·  Programs are easier to change, if needed

·  Programs are easier to write, test, and debug

·  Like most programming languages, Java has facilities to include separate subparts into a program. In other programming languages these subparts are called functions, subroutines, subprograms,  procedures or modules. In Java these subparts are called methods. They are like miniature programs; you can put them together to form a larger program.

·  Several advantages of using methods in a Java program:

·  While working on one method, you can focus on just that part of the program and construct it, debug it, and perfect it.

·  Different people can work on different methods simultaneously, when working on large applications.

·  If a method is needed in more than one place in a program, or in different programs, you can write it once and use it many times. The fact that the code is reusable is very important in program design: the final program is more modular and redundancies are avoided.

·  Because each method performs some particular task, the method itself can work as a black box.

·  Using methods greatly enhances the programs readability because it reduces the complexity of the method main.

·  When to use methods in a Java program? Any module can be coded into a method but the decision should be based on whether the overall program is easier to understand as a result. Using appropriate methods will make the program more readable and future changes more convenient.

·  Terms used with Java methods:

·  Invoking a method using its name == calling the method

·  When a method completes its processing, it returns to its caller.

·  A method can pass information to the caller by returning a result (value-returning methods) or not (void methods)

·  The caller can pass information to a method by using parameters (parameter == a value passed to a method by its caller.)  A formal parameter is a variable declared in the method heading (method definition). An actual parameter is a variable (or expression) listed in a call to a method.


Note: the formal parameter and the actual parameter can have different names.


Example:
    printLines(2);
    printLines(n);
    printLines(n * n);


Example:
    public static void printLines(int n, char whichChar); //method signature
    printLines(5, '*'); //method call

·  Method signature = method name + the parameter types.

·  The execution of a Java program always begins with the first statement in the method main. User-defined methods execute only when they are called. A call to a method transfers control from caller to the method called. In the method call statement, you must specify only actual parameters, not the data type or method type. Control goes back to caller when the method exits. You can put methods within a class in any order.

·  Java has 2 types of methods:

·  Predefined methods, methods that are already written and provided by Java

·  User-defined methods, methods that the programmer creates.

2. Predefined Methods in Java
 

·  In Java, predefined methods are organized as a collection of classes, called class libraries.

·  Example #1:  The class Math   contained in the package java.lang contains mathematical methods.  The method type is the data type of the value returned by the method.  Some predefined methods in the class Math are:  Math.log10(x), Math.abs(x), Math.ceil(x), Math.exp(x), Math.floor(x), Math.log(x), Math.max(x, y), Math.min(x, y), Math.pow(x, y), Math.round(x), Math.sqrt(x), Math.cos(x), Math.sin(x), Math.tan(x)

·  Math method call syntax:

Math.<method name>(<parameter(s)>)

Examples:

 double squareRoot = Math.sqrt(196.0);
 System.out.println(squareRoot);      //14.0
 int absoluteValue = Math.abs(-150);
 System.out.println(absoluteValue);   //150
 System.out.println(Math.min(13, 27) + 2); //15

NOTE: In these examples, all method calls have been used in expressions; they can be printed, stored into a variable, etc. See Value_returning Methods.

·  Example #2:  The  class Character  contained in the package java.lang contains the following methods: Character.isDigit(ch), Character.isLetter(ch), Character.isLowerCase(ch), Character.isUpperCase(ch), Character.isSpaceChar(ch), Character.isWhitespace(ch), Character.toLowerCase(ch), Character.toUpperCase(ch)

·  In general, to use predefined methods of a class in a program, you must import the class from the package containing the class.  By default Java automatically imports classes from the package java.lang. Therefore, if you use a method from the class Math or Character you do not need to explicitly import these classes in your program.

·  A method of a class may contain the reserved word static (in its heading). For example, the method main contains the reserved word static in its heading. If (the heading of) a method contains the reserved word static, it is called a static method; otherwise, it is called a nonstatic method.

·  The heading of a method may contain the reserved word public. If the heading of a method contains the reserved word public, it is called a public method. An important property of a public and static method is that (in a program) it can be used (called) using the name of the class, the dot operator, the method name, and the appropriate parameters (Math.pow(x, y), Character.toLowerCase(ch))


3. User-Defined Methods in Java

User-defined methods in Java are classified into two categories: value-returning methods (methods that have a return type) and void methods (methods that do not have a return type).

1. void  methods - do not return a value and are not called from within an expression. The method call appears as a complete, stand-alone statement.
2. Value-returning methods - receive some data through the list of parameters, compute a single value (and JUST one), and return this value to the calling code. The caller invokes (calls) such a method by using its name and parameters list in an expression

·  In order to use methods in your programs, you must know:

  1. Modifiersindicate the visibility of the method, that is, where in a program the method can be used (called). Some of the modifiers are public (method made available to other classes),, private (method available only within its own class), protected, static, abstract, and final - you will learn about these later.
  2. The name of the method: Although a method name can be any legal identifier, method names are restricted by coding conventions. By convention, method names should be a verb in lowercase or a multi-word name that begins with a verb in lowercase, followed by adjectives, nouns, etc. In multi-word names, the first letter of each of the second and following words should be capitalized. Here are some examples: runThis, getStudentInfo, getFinalData, compareTo, setCoordinates, isFull.
  3. The number of parameters, if any.
  4. The data type of each parameter. The parameter list has to appear in parenthesisa comma-delimited list of input parameters, preceded by their data types, enclosed by parentheses, ( ). If there are no parameters, you must use empty parentheses.
  5. For value-returning methods: The data type of the value computed (= value returned) by the method, called the type of the method. void methods don't return a value.
  6. The code required to accomplish the task, enclosed between braces.


NOTE #1:  1 - 5 =  the heading of the method; 6 =  the body of the method; 1 - 6 = the definition of the method.
NOTE #2:  For predefined methods, software companies do not give out the actual source code, which is the body of the method (6).
NOTE #3:  A methods definition can contain several blocks.
NOTE #4: Cannot nest methods: cannot include the definition of one method in the body of another method.

3.1 void Methods in Java:
 

·  A void method:

MethodName(ActualParameterList);

·  Syntax for a void method:

modifier(s) void methodName(formal parameter list){//method heading
    //method body
    statements
    ...
    ...
}

·  Syntax for formal parameter list:

dataType identifier, dataType identifier,...

·  Syntax for actual parameter list (used in method call):

expression or variable, expression or variable, ...

·  Example #1:
//***********************************************************
// This program prints a "Welcome Home" message
// Will use 2 void methods
//***********************************************************
public class Print1 {

public static void main(String[] args){
    print2Lines(); // method call
    System.out.println("Welcome Home!");
    print4Lines(); // method call
}
//***********************************************************
// Method definition
// This method prints two lines of asterisks
//***********************************************************
public static void print2Lines(){ // method heading
    System.out.println("***************");
    System.out.println("***************");
}
//***********************************************************
// Method definition
// This method prints four lines of asterisks
//***********************************************************
public static void print4Lines(){ // method heading
    System.out.println("***************");
    System.out.println("***************");
    System.out.println("***************");
    System.out.println("***************");
}

}
 

·  Example #2: Modify the program to have just one void method - any number of lines
//***********************************************************
// This program prints a "Welcome Home" message
// Will use one void method
//***********************************************************
public class Print2 {

public static void main(String[] args){
    printLines(2); // method call
    System.out.println("Welcome Home!");
    printLines(4); // method call
}
//******************************************************
// Method definition
// This method prints n lines of asterisks
//******************************************************
public static void printLines(int n){ // method heading
    for(int line = 1; line <= n; line++){
        System.out.println("***************");
    }
}

}
 

·  Example #3: Modify the program to have just one void method - any number of lines, any character (not only *)
//***********************************************************
// This program prints a "Welcome Home" message
// Will use one void method
//***********************************************************
public class Print3 {

public static void main(String[] args){
    printLines(2, '*'); // method call
    System.out.println("Welcome Home!");
    printLines(4, '+'); // method call
}
//******************************************************
// Method definition
// This method prints n lines of any character
//******************************************************
public static void printLines(int n, char what){ // method heading
    for(int line = 1; line <= n; line++){
        for(int c = 1; c <= 15; c++){ //15 characters/line in output
            System.out.print(what);
        }
        System.out.println();
    }
}

}
 

·  Example #4: Modify the program to have just one void method - any number of lines, any character (not only *), any number of characters/line (not only 15)
//***********************************************************
// This program prints a "Welcome Home" message
// Will use one void method
//***********************************************************
public class Print4 {

public static void main(String[] args){
    printLines(2, '*', 15); // method call
    System.out.println("Welcome Home!");
    printLines(4, '+', 20); // method call
}
//******************************************************
// Method definition
// This method prints n lines of any character
//******************************************************
public static void printLines(int n, char what, int howMany){ // method heading
    for(int line = 1; line <= n; line++){
        for(int c = 1; c <= howMany; c++){
            System.out.print(what);
        }
        System.out.println();
    }
}

}
3.2 Value-Returning Methods in Java


 

modifier(s) returnType methodName(formal parameter list){//method heading
    //method body
    statements
    ...
    return ...;
}

 
dataType identifier, dataType identifier,...

 
expression or variable, expression or variable, ...

 

 
return expr;
 

 
public static int min(int x, int y) {
   if (x < y) {
      return x;
   }
   else {
      return y;
   }
}

 
public static String weekdayName(int day) {
   switch (day) {
     case 1: return "Sunday";
     case 2: return "Monday";
     case 3: return "Tuesday";
     case 4: return "Wednesday";
     case 5: return "Thursday";
     case 6: return "Friday";
     case 7: return "Saturday";
     default: return "Illegal value";
   }
}

 
public static boolean isDivisibleBy(int x, int y) {
   return x % y == 0;
}

The method above has better design than the next one (similar outcome, technically correct, but not elegant):
 

public static boolean isDivisibleBy(int x, int y) {
   if (x % y == 0) {
      return true;
   }
   else {
      return false;
   }
}

min_value = min(a, b); //assignment
...
some_value = min(a, b) + 20; //calculation
...
System.out.println("Min = " + min(a, b)); //print


//method heading
public static double calculateSomething(double param1, int param2, double param3) {
    //method body
    double someDouble;
    //do the calculations here
    return someDouble;
}


public static void main(String[] args){
    double a, c, result;
    int b;
    result = calculateSomething(a, b, c);
    ...
}


public static double calculateSomething(double, int, double)

4. Overloading Methods
 

·  Typically, a method has a unique name within its class. However, a method might have the same name as other methods due to method overloading.

·  Method overloading == methods within a class can have the same name if they have different parameter lists.

·  Java supports overloading methods, and Java can distinguish between methods with different method signatures. Overloaded methods are differentiated by the number and the type of the parameters passed into the method.

·  NOTE #1: Cannot declare more than one method with the same name and the same number and type of parameters, because the compiler cannot tell them apart.

·  NOTE #2: The compiler does not consider return type when differentiating methods ==> cannot declare two methods with the same signature even if they have a different return type. Example:

public void someMethod(int x, double y)
public int someMethod(int x, double y)

These method signatures have the same name and same formal parameter list. Incorrect overloading --> will generate a syntax error, even though return types are different.

·  NOTE #3: Overloaded methods should be used sparingly, as they can make code much less readable.

·  Program Sample:
 
public class Print5 {

public static void main(String[] args){
    printLines(2, '*'); // method call
    System.out.println("Go Home!");
    printLines(4, '+', 25); // method call
    System.out.println("Welcome Home!");
    printLines(5);// method call
    System.out.println("Welcome Home Again!");

}
//*******************************************************
// Method definition
// This method prints n lines of  15 asterisks
//*******************************************************
public static void printLines(int n){ // method heading
    for(int line = 1; line <= n; line++)
        System.out.println("***************");
    }
}
//*******************************************************
// Method definition
// This method prints n lines of 15 characters
//*******************************************************
public static void printLines(int n, char what){ // method heading
    for(int line = 1; line <= n; line++){
        for(int c = 1; c <= 15; c++){ //15 characters/line in output
            System.out.print(what);
        }
       System.out.println();
    }
}
//*******************************************************
// Method definition
// This method prints n lines of any number of characters
//*******************************************************
public static void printLines(int n, char what, int howMany){ // method heading
    for(int line = 1; line <= n; line++){
        for(int c = 1; c <= howMany; c++){
            System.out.print(what);
        }
        System.out.println();
    }
}

}

5. Scope of Identifiers within a Class
 

·  Scope = The region of a program where it is legal to use an identifier (names you choose for constants, variables, methods). Can also be defined as the area of a program where an identifier is visible (exists).

·  Scope:

·  Scope Rules:

public static void illegalStuff(){
    int x;
    //some block (loop)
    {
        double x; //illegal declaration, x was already declared
        ...
    }
}
In this example, the second declaration of the variable x is illegal because x was previously declared in the outer block.

·  Example #1:

public static void scopeEx1() {
    int x = 5; //x is local to the method
    for (int i = 1; i <= 10; i++) { //i is local to the for loop
        System.out.println(x);
    }
    // i no longer exists here
} // x no longer to exist here

·  It is illegal to try to use a variable outside of its scope. Example #2:

public static void main(String[] args) {
    ex2(); //method call
    System.out.println(x); // illegal! x is local in method ex2()
    for (int i = 1; i <= 10; i++) {
        int y = 5;
        System.out.println(y);
    }
    System.out.println(i); // illegal! i is local inside for statement
    System.out.println(y); // illegal! y is local inside for statement
}
//method definition
public static void ex2() {
    int x = 10;
    System.out.println(x);
}

·  Example #3:

import java.util.Scanner;
public class ScopeEx3 {

public static final double TAX_RATE = 0.05; //global constant
double tipRate; //global variable (AVOID!)
public static void main(String[] args) {
    //age and bill local to main()
    int age;
    double bill;
    //a, b and tax cannot be used here (local to method handle)
    // TAX_RATE and tipRate can be used here (global)
    ...
    ...
    //method call
    handle(age, bill);
}
//method definition
public static void handle(int a, float b) {
    float tax;
    // a, b, and tax local to method handle
    // age and bill cannot be used here (local to main())
    // TAX_RATE and tipRate can be used here (global)
    ...
    ...
}

}

·  Example #4 (Scope Rules):

public class ScopeEx4 {
    static final double RATE = 10.50;
    static int z;
    static double tax;
    public static void main(String[] args) {
        int n;
        double x, z;
        char ch;
        ...
        ...

    }
    public static void first(int x, char y){
        ...
        ...

    }
    public static int w;
    public static void second(int first, int z) {
        char ch;
        int a;
        //start block
        {
            int x = 12;
            ...
            ...

        } //end block
        ...
    }
}

·  Example #5: What is the output?

 

public class ScopeEx5 {
    public static void main(String[] args) { 
        int x = 1, y = 2;
        System.out.println("x = " + x + " y = " + y);
        print1(); //method call
        print2(); //method call
        System.out.println("x = " + x + " y = " + y);
    }

        void print1(){ // method definition
            int x; // local variable
            x = 3;
            System.out.println("x = " + x);
        }

        void print2(){ // method definition
            int y; // local variable
            x = 4;
            System.out.println("y = " + y);
        }
    }

public class ScopeEx5 {
    public static void main(String[] args) { 
        int x = 1, y = 2;
        System.out.println("x = " + x + " y = " + y);
        print1(); //method call
        print2(); //method call
        System.out.println("x = " + x + " y = " + y);
    }

       static void print1(){ // method definition
            int x; // local variable
            x = 3;
            System.out.println("x = " + x);
         }

       static void print2(){ // method definition
            int y; // local variable
            x = 4;
            System.out.println("y = " + y);
         }
    }

OUTPUT:
2 errors found:
File: C:\COSC236-JAVA\ZI\Labs\ScopeEx5.java  [line: 6]
Error: non-static method print1() cannot be referenced from a static context
File: C:\COSC236-JAVA\ZI\Labs\ScopeEx5.java  [line: 7]
Error: non-static method print2() cannot be referenced from a static context

OUTPUT:
x = 1 y = 2
x = 3
y = 4
x = 1 y = 2

6. Value vs. Reference Semantics

Consider the following program to swap two integer variables:

import java.util.Scanner;
public class Swap_1 {
    public static void main(String[] args) {
        int a, b, temp;
        Scanner input = new Scanner(System.in);
        System.out.print("Enter 2 integers: ");
        a = input.nextInt();
        b = input.nextInt();
        System.out.println("Initial values, before swap: " + a + " and " + b);
      //swap a and b
        temp = a;
        a = b;
        b = temp;
        System.out.println("Final values, after swap: " + a + " and " + b);
    }
}
OUTPUT:
Enter 2 integers: 20 100
Initial values, before swap: 20 and 100
Final values, after swap: 100 and 20

Now consider writing the same program using a method to swap 2 integer variables:

import java.util.Scanner;
public class Swap_2 {
    public static void main(String[] args) {
        int a, b, temp;
        Scanner input = new Scanner(System.in);
        System.out.print("Enter 2 integers: ");
        a = input.nextInt();
        b = input.nextInt();
        System.out.println("Initial values, before swap: " + a + " and " + b);
        //swap a and b: call method
        swap(a, b);
        System.out.println("Final values, after swap: " + a + " and " + b);
    }

    public static void swap(int a, int b){
        int temp;
        temp = a;
        a = b;
        b = temp;
    }
}
OUTPUT:
Enter 2 integers: 20 100
Initial values, before swap: 20 and 100
Final values, after swap: 20 and 100

Obviously something is not right in this program, although the algorithm used is correct. The reason: In Java primitive data types are passed by value, objects are passed by reference.

Primitive data type variables as parameters - value parameters:

Function signature:  void printLines(int)
Function call: 
printLines(lineCount); //actual param = variable name
Other valid function call:
printLines(4); //actual param = constant
Other valid function call:
printLines(2 * (int) Math.sqrt(lineCount)); //actual param = expression
Formal parameter
numLines receives a copy of the value of lineCount (actual parameter)
The method printLines cannot change the actual parameter
lineCount

Objects as Parameters - reference parameters:

7. Sample Programs
Program #1: Java Program - Value returning methods, overloading methods

import java.util.Scanner;
class MethodSample {
  public static void main(String[] args) {
    Scanner input = new Scanner(System.in);
    int choice;
    int n, sum_n, base, pow_xn;
    double base_f, pow_xn_f;
    choice = menu(); // method call
    while(choice != 0) {
      switch(choice) {
        case 1:
          System.out.print("Enter a positive integer: ");
          n = input.nextInt();
          while(n <= 0) {
             System.out.print("\nERROR! Should be positive! Reenter: ");
             n = input.nextInt();
          }
          sum_n = sum(n); // method call
          System.out.println("The sum of all integers between 1 and " + n + " is " + sum_n);
          break;
        case 2:
          System.out.print("Enter base, exponent (positive integers): ");
          base = input.nextInt();
          n = input.nextInt();
          while(base <= 0 || n <= 0) {
            System.out.print("\nERROR! Should be positive! Reenter: ");
            base = input.nextInt();
            n = input.nextInt();
          }
          pow_xn = power(base, n); // method call
          System.out.println("pow(" + base + " , " + n + ") is " + pow_xn);
          break;
        case 3:
          System.out.print("Enter base (float) and exponent(any integer): ");
          base_f = input.nextDouble();
          n = input.nextInt();
          pow_xn_f = power(base_f, n); // method call
          System.out.println("pow(" + base_f + " , " + n + ") is " + pow_xn_f);
          break;
      }// close switch
      choice = menu();
    } //close while
  }//close main()

  // Method definitions
  // menu method
  public static int menu() {
    int option;
    Scanner input = new Scanner(System.in);
    do {
      System.out.println("Your options are:");
      System.out.println("-----------------");
      System.out.println("\t1)Sum(n)");
      System.out.println("\t2)Power(x, n), x integer, n positive");
      System.out.println("\t3)Power(x, n), x float");
      System.out.println("\t0)EXIT");
      System.out.print("\nPlease enter your option: ");
      option = input.nextInt();
      System.out.println();
    } while(option < 0 || option > 3);
    return option;
  }

  // sum method
  public static int sum(int n) {
    int i, sum_n = 0;
    for(i = 1; i <= n; i++)
      sum_n += i;
    return sum_n;
  }

  // power method, base and exponent positive integers
  public static int power(int x, int n) {
    int i, pow_n = 1;
    for(i = 1; i <= n; i++)
      pow_n *= x;
    return pow_n;
  }

  // power method, base float, any exponent
  public static double power(double x, int n) {
    int i;
    double pow_n = 1;
    if(n < 0) {
      n = -n;
      for (i = 1; i <= n; i++)
        pow_n = pow_n / x;
    }
    else
      for(i = 1; i <= n; i++)
        pow_n *= x;
    return pow_n;
  }
} //close class

/* OUTPUT:
Your options are:
-----------------
 1)Sum(n)
 2)Power(x, n), x integer, n positive
 3)Power(x, n), x float
 0)EXIT
Please enter your option: 2
Enter base, exponent (positive integers): 3 6
pow(3 , 6) is 729
Your options are:
-----------------
 1)Sum(n)
 2)Power(x, n), x integer, n positive
 3)Power(x, n), x float
 0)EXIT
Please enter your option: 3
Enter base (float) and exponent(any integer): 3 -6
pow(3.0 , -6) is 0.0013717421124828531
Your options are:
-----------------
 1)Sum(n)
 2)Power(x, n), x integer, n positive
 3)Power(x, n), x float
 0)EXIT
Please enter your option: 3
Enter base (float) and exponent(any integer): 2 -3
pow(2.0 , -3) is 0.125
Your options are:
-----------------
 1)Sum(n)
 2)Power(x, n), x integer, n positive
 3)Power(x, n), x float
 0)EXIT
Please enter your option: 3
Enter base (float) and exponent(any integer): 2.5 -3
pow(2.5 , -3) is 0.064
Your options are:
-----------------
 1)Sum(n)
 2)Power(x, n), x integer, n positive
 3)Power(x, n), x float
 0)EXIT
Please enter your option: 1
Enter a positive integer: -6
ERROR! Should be positive! Reenter: 10
The sum of all integers between 1 and 10 is 55
Your options are:
-----------------
 1)Sum(n)
 2)Power(x, n), x integer, n positive
 3)Power(x, n), x float
 0)EXIT
Please enter your option: 1
Enter a positive integer: 89
The sum of all integers between 1 and 89 is 4005
Your options are:
-----------------
 1)Sum(n)
 2)Power(x, n), x integer, n positive
 3)Power(x, n), x float
 0)EXIT
Please enter your option: 0
*/

Program #2: Java Program - Value Parameters (primitive data types)

import java.util.Scanner;
public class passByValue {
    public static void main(String[] args) {
        int x;
        Scanner input = new Scanner(System.in);
        System.out.print("Enter integer: ");
        x = input.nextInt();
        System.out.println("Initial value, before method call: " + x);
        valueMethod(x); //method call
        System.out.println("Final value, after method call: " + x);
    }
    //method definition
    public static void valueMethod(int a){
        System.out.println("Parameter value, method entry: " + a);
        a = 1001;
        System.out.println("Parameter value, method exit: " + a);
    }
}
OUTPUT:
Enter integer: 25
Initial value, before method call: 25
Parameter value, method entry: 25
Parameter value, method exit: 1001
Final value, after method call: 25


Additional Resources:
1. (Sun) API specification for version 6 of the Java Platform, Standard Edition:  http://java.sun.com/javase/6/docs/api/
2. (Sun) The Java Tutorials, Defining Methods: http://java.sun.com/docs/books/tutorial/java/javaOO/methods.html
3. (Sun) The Java Tutorials, Exceptions: http://download.oracle.com/javase/tutorial/essential/exceptions/index.html


References:
[1] Building Java Programs: A Back to Basics Approach, by Stuart Reges, and Marty Stepp, Addison Wesley, 2008.
[2] Java Programming: From Problem Analysis to Program Design, by D.S. Malik, Thomson Course Technology, 2008