Home Previous Next

CSC110AB::Lecture Note::Week 14
Assignments | Handouts | Resources | Email Thurman {Twitter::@compufoo Facebook::CSzero}
GDT::Bits:: Time  |  Weather  |  Populations  |  Special Dates

Overview Assignment(s): Code: Dog.java | Roll2Die.java | Change.java | MyTwitter.java

Introduction to Methods

Lowest level ideas become expressions (EXPRs), expressions are grouped into statements, and statements are grouped together into blocks and methods.

A method is a set of statements that have been collected together and given a name.

Methods break large computing tasks into smaller ones, and enable people to build on what others have done instead of starting over from scratch. Methods support reuse.

Methods hide details of operation from parts of the program that don't need to know about them. Methods support information hiding.

Methods usually consist of zero or more statements, and a collection of local data. Methods support encapsulation.

Programs generally consist of many small methods rather than a few big ones. Methods support modularity.

Repetitive expressions should be grouped into a method. Methods eliminate duplicate code.

Additional benefits derived from using methods:

Methods that perform generic tasks can be added to a class library. Library methods can be used in multiple programs. Library methods are static methods.

Java doesn't allow for global methods; i.e. every method must be defined in a class.

Static methods are class methods; whereas non-static methods are instance methods.

Instance methods typically contain code that understands and manipulate an object's state.

Static methods can be invoked in one of two ways:

   ClassName.methodName(...);
   objectVariable.methodName(...);
Instance methods can only be invoked using an object variable.

Every instance method has access to an object variable named this. The this object variable points-to (or is a handle-to, or is a reference-to) the recipient object.

A recipient object is the object for which a method has been called.

Statically defined methods do not have access to the this object variable.

Calling an instance method is equivalent to sending a message to an object. The values of the arguments, if any, make up the content of the message. If no arguments are used, then you have an empty message.

Method arguments are passed by-value. All argument EXPRs are evaluated prior to the method being called.

[review Underline.java]

{TopOfPage} {Oracle.com::API Specification | Tutorial} {GDT::Java Resources} {Eclipse IDE} {Udacity} {udemy} {CodingGround (online IDE)


Method Terminology

The act of executing a set of statements associated with a method is known as calling the method. If method A calls method B, then method A is referred to as the calling or caller method and method B is the called method.

Arguments are a list of EXPRs that are evaluated and whose values are passed to the method. (Note: Java is a "pass-by-value" languages.) A method does not need to take arguments. If method A calls method B, then arguments allows method A to communicate (pass) information to method B.

Arguments, if any, that are passed to a method B, are parameters within method B. Parameters are treated as initialized local variables.

When a method is done, it returns to the caller by executing a return statement.

Methods can "return a value" back to the caller; thus, if method A calls method B, then the return value allows method B to communicate with method A.

{TopOfPage} {Oracle.com::API Specification | Tutorial} {GDT::Java Resources} {Eclipse IDE} {Udacity} {udemy} {CodingGround (online IDE)


Calling a Method

A method is called by specifying the method's name, followed by a left paren, a comma separated list of arguments (if any) and a right paren. Comma when used in this context is not the sequence operator.

Example.

   int rv = x(200, 210);
      //call the method  x  passing it two values: 200 and 210
      //capture the return value from  x  in the variable rv

   System.beep();
      //call the method  beep()  implemented in the System class
      //no arguments are passed, nor does the method return any value

A method call is a sequence point: every EXPR that comprises an argument is evaluated prior to the method being called. The order in which the arguments are evaluated is left-to-right.

Java is a "call-by-value" language: the arguments are evaluated and their respective values are passed to the method.

{TopOfPage} {Oracle.com::API Specification | Tutorial} {GDT::Java Resources} {Eclipse IDE} {Udacity} {udemy} {CodingGround (online IDE)


Method Definitions

The method definition contains the statements that comprise a method. The definition of a method is also referred to as its implementation.

A method declaration consists of two parts: a header and a body.

Method statements are enclosed in {}'s and are referred to as the method body.

The body of a method consists of zero more variable declarations/definitions and zero or more statements.

At most one access specifier modifier can be used when a method is defined (public, or private or protected). If an access is not used, then it defaults to package access.

Class methods are defined using the static modifier. Instance methods are defined without using static.

Examples.

   public static int x(int n1, int n2) {
      //this is the method body...
   }

   public static void y(float f, char c, int i) {
      //this method doesn't return a value; it takes three
      //   parameters (a float, a char and an int)
      ...
      if (i) return;
      ...
   }

When a method is defined, each parameter, if any, must be specified with a type and a name. Parameter type-name pairs are separated by comma's. [parameter type list]

Parameters can be thought of as initialized local variables (i.e. space is allocated for them from the stack and they are initialized to the value of the arguments that are passed).

Variables declared inside of a method body are visible only with that block of code. These variables are referred to as a local variables.

A method definition can contain multiple return statements; however, many programmers are of the opinion that a method should have only one exit point.

A stub method is a method that contains no statements.

Every method definition should begin a method comment block that desribes what the method does.

A method signature consists of the method name and the parameter type list enclosed in parentheses.

An instance method can access and/or modify an object's state. A static method is invoked on behalf of an entire class, not on a specific object instantiated from that class.

A static method can only access static fields and static methods of a class.

Method Modifiers
   access specifiers (public, private, protected)
   abstract (method has no body)
   static (class method)
   final (method cannot be overridden)
   synchronized (used with threads)
   native (written in some other language)
   strictfp (strict floating-point)

{TopOfPage} {Oracle.com::API Specification | Tutorial} {GDT::Java Resources} {Eclipse IDE} {Udacity} {udemy} {CodingGround (online IDE)


Method Comment Blocks

Every method should begin with a method comment block. The method comment block contains - at a minimum - the name of the method, a list of arguments that it receives, a description of its return value (if any), and a brief description of what the method does. In addition, any side-effects (or outputs) performed by the method should be documented.

The following is an example function comment block.

   /**
    * name:  isVowel
    * parameters:  char -- a character
    * returns:  true if parameter value is vowel; false otherwise
    * description:  This method tests to see if a character is a
    *               the vowel (a, e, i, o, u).  The character can
    *               be either upper- or lower-case.
    */

Cay Horstmann quote.

"The description of a method comment block does not document the implementation but the idea."

{TopOfPage} {Oracle.com::API Specification | Tutorial} {GDT::Java Resources} {Eclipse IDE} {Udacity} {udemy} {CodingGround (online IDE)


Method Return Value

A method communicates back to the caller by returning a value.

The type of value returned by a method (i.e. the return-type) is specified when the method is defined.

A method does not have to return a value. In these cases, the return-type void is used.

Other points.

The syntax of the return statement is as follows.

   return;       //used when the return-type of the method is void

   return EXPR;
      
      EXPR is evaluated.  The result of the evaluation must
      match the return-type of the method.  If it doesn't,
      then explicit type-cast is needed.  For example,
      if the return-type of the method is  int  , then

         return (int)3.14;  

      will cause the 3.14 double to be converted to an int; therefore,
      the calling method will be returned the value 3.

   Optionally, the return EXPR can be enclosed in parens.

      return (EXPR);  
      return (3.14);           or   return 3.14;
      return (i + 3 * j);      or   return i + 3 * j;
      return (i > 4);          or   return i > 4;

If a method returns a value, then it is the caller's responsibility to examine the return value.

If a methods's return-type is void, then return statements, if any, cannot have any expressions.

{TopOfPage} {Oracle.com::API Specification | Tutorial} {GDT::Java Resources} {Eclipse IDE} {Udacity} {udemy} {CodingGround (online IDE)


Method Overloading

Method overloading is the ability to give different methods the same name.

Stroustrup says.

Most often, it is a good idea to give different methods different names, but when some methods conceptually perform the same task on objects of different types, it can be more convenient to give them the same name.

Use descriptive overloaded method names to describe similar operations, not different behaviors.

   Good:
      int max(int, int);        //find max of two ints
      float max(float, float);  //find max of two floats

   Not so Good:
      void draw(Image);        //draw an image
      void draw(Card);         //draw a card 

The following is an example of overloaded methods having the name print.

   void print(int), print(double), print(long), print(char), 
        print(int, int), print(double, double);

   char c;
   short s;
   int i;
   float f;

   print(c);            // invoke print(char)
   print(i);            // invoke print(int)
   print(s);            // invoke print(int); s promoted to int
   print(f);            // invoke print(double); f promoted to double
   print('A');          // invoke print(char); 'A' is a char
   print(200);          // invoke print(int); 200 is an int
   print(200L);         // invoke print(long); 200L is a long
   print(99.9);         // invoke print(double); 99.9 is a double
   print(i, i);         // invoke print(int,int)
   print(i, 'a');       // invoke print(int,int); 'a' promoted to int
   print(s, 'A');       // invoke print(int,int); s - 'A' promoted to int
   print(200L, i);      // invoke print(int,int)
   print(i, 3.14);      // invoke print(double,double)

When print() is called, the compiler must figure out which of the methods with the name print is to be invoked. This is done by comparing the types of the actual arguments with the types of the parameters of all methods called print. The method with the best match is called; if none exist, then a compile-time error.

Definition.

The signature of a method consists of the name of a method and its ordered set of parameter data types.

Criteria used to determine a match (partial).

  1. exact match of method call arguments with an overloaded method signature
  2. trivial conversions (exact match after applying promotions to argument data types -- char ==> int, short ==> int, float ==> double)
  3. exact match after programmer defined conversions (e.g. typecast)

{TopOfPage} {Oracle.com::API Specification | Tutorial} {GDT::Java Resources} {Eclipse IDE} {Udacity} {udemy} {CodingGround (online IDE)


Lifetime and Visibility (Scope)

Lifetime is the period, during execution of a program, in which a variable or method exists.

Visibility is the portions of the program in which a variable or method can be referenced by name (also referred to as scope (scope units: class, method, block).

Local variables are declared and/or defined within a block (either a method or a compound statement).

Local variables do not retain their values across method calls. Local variables cannot be defined static.

Global variables are declared and/or defined outside of any method. These are either static class variables or they are instance variables.

{TopOfPage} {Oracle.com::API Specification | Tutorial} {GDT::Java Resources} {Eclipse IDE} {Udacity} {udemy} {CodingGround (online IDE)


Introduction to Classes

A class is a blueprint or template that describes an object.

Class Syntax
   classDeclaration {
      classBody
   }
Syntax of a class declaration:
   [ modifiers ] class ClassName [ extends SuperClassName ]
                                 [ implements InterfaceNames ]

   Some example modifiers are:  public, abstract, final 
   If no modifier is specified, then it defaults to "package."

The class body contains static data members, instance data members, static methods and instance methods.

By convention, class names begin with an uppercase letter.

About Constructor Methods

A constructor is a special method that is used to help guarantee that objects are initialized to a "valid" or "sane" state when they are created (instantiated).

{TopOfPage} {Oracle.com::API Specification | Tutorial} {GDT::Java Resources} {Eclipse IDE} {Udacity} {udemy} {CodingGround (online IDE)


Constructors

Objects are instantiated (created) using the new operator.

   Date today = new Date();
   String greeting = new String("Hello, World");
   Integer age = new Integer(42);
   Vector guesses = new Vector();

In a nutshell, the new operator determines the sizeof of the object and allocates memory for the object from the heap. If the memory allocation works, then it wants to initialize the object. By default, the memory allocated for an object is set to all-bits-zero. Integral and floating points instance variables are set to 0, boolean variables are set to false, and object variables are set to null.

In many cases, programmers want to control the initialization of objects when they are instantiated. This is accomplished by implementing a constructor method or methods.

If a class contains a constructor, then the new operator automatically "calls" it after memory has been allocated.

The constructor is responsible for initializing the newly created object. They help ensure that objects are initialized to valid states prior to being used.

A constructor is a special method having the same name as its class. Programmer's never call constructors directly. Constructor methods do not return value; consequently, a return-type is not specified when a constructor is declared.

   public class Foo {
      private int i;

      public Foo(int value) {    //no return-type specified
         this.i = value;         //or we could write:  i = value;
      }

      public static void main(String[] argv) {
         Foo f = new Foo(200);
      }
   }

A class can contain more than one constructor and the one that is invoked depends on the type and number of arguments passed. Multiple constructors are possible because Java supports method overloading.

   public class Foo {
      private int i;

      public Foo() {
         i = -1;
      }

      public Foo(int value) {
         this.i = value;         //or  i = value
      }

      public static void main(String[] argv) {
         Foo b = new Foo();
         Foo a = new Foo(200);
      }
   }

A constructor that does not receive any parameters is called the default constructor.

A "family" of constructors allow objects to be initialized using various "levels" of initialization.

When you have a "family" of constructors, then you should try to implement them using only one of them. This can be accomplished using the this keyword as if you were calling a method named this.

   public class Foo {
      private int i;

      public Foo() {
         this(-1);               //invoke the Foo(int) constructor
      }

      public Foo(int value) {
         this.i = value;         //or  i = value
      }

      public static void main(String[] argv) {
         Foo b = new Foo();
         Foo a = new Foo(200);
      }
   }

If a constructor encounters an un-recoverable error condition, then it typically "throws" an exception.

   public class AgeTracker {
      private int age;
      ...
      public AgeTracker(int age) {
         if (age < 0) 
            throw new IllegalArgumentException("Negative ages not valid.");
         this.age = age;
      }
      ...
   }

Constructors cannot be used to re-initialize objects because programmers cannot call constructors directly. If re-initialization is necessary, then the initialization steps should be made into a stand-alone method that client's can call. Note: constructors should call this stand-alone method also in order to avoid duplicate code.

Most constructors are defined to be public, but they can be private. Making a constructor private prohibits objects to be created from your class.

{TopOfPage} {Oracle.com::API Specification | Tutorial} {GDT::Java Resources} {Eclipse IDE} {Udacity} {udemy} {CodingGround (online IDE)


class Object

The Object class is the superclass of all classes in Java; it is the root of the Java class hierarchy.

Every Java application derives from (or extends) the Object class (i.e. every object is an Object).

The Object class is defined in the java.lang package.

   public class Foo extends java.lang.Object ...

         or

   public class Foo extends Object ...

Every method defined in the Object class is available in all of its subclasses.

In many cases, the behavior that is inherited from the Object does not work for objects created from other classes; consequently, these classes override many of the methods defind in the Object class.

The following Object methods are almost always overridden:

   boolean equals(Object obj);

      // compares this object with  obj  for equality; by default, 
      // two objects are equal if they point to the same object;

   String toString();

      // returns the String representation of this object; 
      // overriding this method allows the following:

         Foo f = new Foo();
         String s = f.toString();

To successfully override a method, its signature must match identically to the signature of the method being overridden.

[DemoObject.java]

{TopOfPage} {Oracle.com::API Specification | Tutorial} {GDT::Java Resources} {Eclipse IDE} {Udacity} {udemy} {CodingGround (online IDE)


Wrapper Classes

The Java class library comes with a set of Number classes that provide an object wrapper for their values.

   Boolean f = new Boolean(true);

   Byte b = new Byte(11);
   Character c = new Character('a');
   Short s = new Short(210);
   Integer i = new Integer(50000);
   Long l = new Long(19990909);

   Float f = new Float(3.14);
   Double d = new Double(39293.29393);

Wrapper objects are immutable (i.e. they cannot be modified once they are created).

Wrapper objects cannot be used in arithmetic operations. If you must do arithmetic, then you must use access methods to obtain their numeric values.

   Integer i = new Integer(100);
   int j = 52 * i.intValue();

Typically, two wrapper objects are compared for equality using an overridden equals() -- not the equality operator.

   Integer i1 = new Integer(210);
   Integer i2 = new Integer("210");

   if (i1 == i2)
      System.out.println("this will never print");

   if (i1.equals(i2))
      System.out.println("the object values are both 210");

The Character class provides an object wrapper for char values (Unicode characters). This class does not derive from Number class.

Why are wrapper classes needed? To handle cases where methods are used that operate on objects rather than primitive data types.

The integral wrapper classes contain static methods that can be used to convert String objects containing numbers into numbers. Examples.

   int i = Integer.parseInt("123");
   long l = Long.parseLong("123");
   byte b = Byte.parseByte("99");

   String n = new String("123");
   int j = Integer.parseInt(n);

Each wrapper class (except Boolean) contains manifest constants (i.e. static final defined class variables) named MAX_VALUE and MIN_VALUE that contain the maximum and minimum values that can be stored in variables of the primitive data types.

   int maxIntValue = Integer.MAX_VALUE;
   byte minByteValue = Byte.MIN_VALUE;
   float maxFloatValue = Float.MAX_VALUE;
   ...
[Wrappers.java]

{TopOfPage} {Oracle.com::API Specification | Tutorial} {GDT::Java Resources} {Eclipse IDE} {Udacity} {udemy} {CodingGround (online IDE)


Home Previous Next