Google
 

 

up previous next contents
Up: 2. Day 2: The Previous: 2.7 Flow control and Next: 2.9 Methods and parameters   Contents

Subsections

2.8 Classes and objects

2.8.1 Introduction

  • Class - the fundamental unit of programming in Java.
  • Classes contain the attributes and behaviors of the objects you will create.
  • Classes define how an object should be created, how it should be destroyed, and how it should behave during it's existence.

2.8.2 Objectives

Upon completion of this section, you should be able to:

  • Define the difference between a Java class and an object.
  • Create a simple Java class.
  • Create constructors for your classes.
  • Define the behavior of your classes.
  • Be able to describe Java's garbage collection process.
  • Declare and initialize instance variables.
  • Access data members and methods of an instance.
  • Discuss nested classes and Interfaces.
  • Write your own complete Java classes.

2.8.3 A Simple Class

  • Each object is an instance of a class.
  • The basics of a class are it's fields and methods (or, attributes and behaviors).
        class Body {
           public long idNum;
           public String nameFor;
           public Body orbits;
           public static long nextID = 0;
        }
    
  • First declare the name of the class:
        Body mercury;
        Body earth;
    
  • mercury and earth are references to objects of type Body.
  • During it's existence, mercury may refer to any number of Body objects.
  • Note - this version of Body is poorly designed.

2.8.4 Fields

  • A class's variables are called fields (or attributes).
  • Every Body object has its own specific instances of these fields, except for nextID.
  • Changing the orbits of one object will not affect the orbits of others.

2.8.5 Access Control and Inheritance

  • We declared many fields of Body to be public; this is not always a good design idea.
  • Four possible access control modifiers:
    • private - members declared private are accessible only in the class itself.
    • protected - accessible in the class itself, and are accessible to, and inheritable by, code in the same package, and code in subclasses.
    • public - accessible anywhere the class is accessible, and inherited by all subclasses.
    • package - members declared with no access modifier are accessible in the class itself and are accessible to, and inheritable by, code in the same package.

2.8.6 Creating Objects

  • Objects are created using the new construct:
        Body sun = new Body();
     
        Body earth;
        earth = new Body();
    
  • This example declare two references (sun, earth) that can refer to objects of type Body.
  • Using new is the most common way to create objects.
  • Java runtime (a) allocates enough space to store the fields of the object, (b) initializes the object, and (c) returns a reference to the new object.
  • If the system can't find enough free space, it runs the garbage collector.
  • If there is not enough free space available, new will throw an OutOfMemoryError exception.

2.8.7 Constructors

  • Constructors have the same name as the class they initialize.
      Body ()
      {
         idNum = nextID++;
      }
    
  • Move the responsibility for idNum inside the Body class.
      Body sun = new Body();    // idNum is 0
      Body earth = new Body();  // idNum is 1
    
  • Constructors can take zero or more parameters.
  • Constructors have no return type.
  • Constructors are invoked after the instance variables of the new object have been assigned their default initial values, and after their explicit initializers are executed.

2.8.7.1 Constructor example

  • The following three classes demonstrate how constructors are called for classes and superclasses.
    public class ParentClass {
      public ParentClass() {
        System.out.println( "ParentClass constructor was called" );
      }
    }
    
    public class ChildClass extends ParentClass {
      public ChildClass() {
        System.out.println( "ChildClass constructor was called" );
      }
    }
    
    public class Main {
      public static void main(String[] args) {
        ChildClass cc = new ChildClass();
      }
    }
    

2.8.8 Methods

  • Here is a sample method for the Body class. The method name is toString.
      public String toString()
      {
          String desc = idNum + " (" + name + ")";
          if orbits != null)
          {
              desc += " orbits " + orbits.toString();
          }
          return desc;
      }
    
  • Returns type String.
  • Methods contain the code that understands and manipulates an object's state.
  • Methods are invoked as operations on an object using the . (dot) operator.
  • Each method takes a specific number of parameters.
  • Each parameter has a specified type - primitive or object.
  • Methods also have a return type (or void).

2.8.8.1 Parameter values

  • All parameter methods are "pass by value".
  • Values of a parameter are copies of the values in the invoking method.
  • When the parameter is an object, the object reference is passed by value.
  • End result: primitives cannot be modified in methods, objects can.

2.8.8.2 Using methods to control access

  • If data fields (attributes) are public, programmers can change them.
  • Generally want to hide the data from programmers that will use the class.
  • If programmers can access a class's fields directly, you have no control over what values they can assign.
  • In the Body example, nextIDshould be private.
  • If necessary, you should provide get methods that allow programmers to determine the current field value, and set methods to modify the value. These are called accessors (get) and mutators (set).

2.8.9 this

  • Typically use this only when needed.
  • Most commonly used as a way to pass a reference to the current object as a parameter to other methods.
  • Often used in a case like this:
      class Pizza
      {
          String topping;
          Pizza (String topping)
          {
              this.topping = topping;
          }
      }
    

2.8.10 Overloading methods

  • Each method has a signature.
  • The signature is (a) the name together with (b) the number and (c) types of parameters.
  • Two methods in the same class can have the same name if they have different numbers or types of parameters.
  • This capability is called overloading.
  • The compiler compares the number and types of parameters to find the method that matches the signature.
  • The signature does not include the return type or list of thrown exceptions, and you cannot overload based on these factors.
      public void aMethod(String s) {}
      public void aMethod() {}
      public void aMethod(int i, String s) {}
      public void aMethod(String s, int i) {}
    

2.8.11 Overriding methods

  • You override the signature of a method from a superclass.
  • Overriding methods must have argument lists with the identical type and order as the superclass.
  • When you override a method of a superclass you should honor the intended behavior of the method.

2.8.12 Static members

  • A static member is a member that exists only once per class, as opposed to once per object.
  • When you declare a field to be static, that means that this field exists only once per class, as opposed to once for each object (such as the nextID field of the Body object).
  • A static method is invoked on behalf of the entire class.
  • A static method can access only static variables and static methods of the class.
        prime = Primes.nextPrime();
        id = Vehicle.currentID();
    

2.8.13 Initialization Blocks

  • A class can have initialization blocks to set up fields or other necessary states.
  • Typically these blocks are static.
  • Most useful when simple initialization clauses on a field declaration need a little help.
        class Primes {
           protected static int[] knownPrimes = new int[4];
           static
           {
              knownPrimes[0] = 2;
              for (int i=1; i<knownPrimes.length; i++)
              {
                 knownPrimes[i] = nextPrime();
              }
           }
        }
    
  • You can also have non-static initialization blocks.

2.8.14 Garbage collection and finalize

  • Java performs garbage collection for you and eliminates the need to free objects explicitly.
  • This eliminates a common cause of errors in C/C++ and other languages (memory leaks). Never have to worry about dangling references.
  • When an object is no longer reachable the space it occupies can be reclaimed.
  • Space is reclaimed at the garbage collector's discretion.
  • Creating and collecting large numbers of objects can interfere with time-critical applications.

2.8.14.1 finalize

  • A class can implement a finalize method.
  • This method will be executed before an object's space is reclaimed.
  • Gives you a chance to use the state of the object to reclaim other non-Java resources.
  • finalize is declared like this:
        protected void finalize() throws Throwable {
           // ...
        }
    
  • Important when dealing with non-Java resources, such as open files.
  • Example: a class that opens a file should provide a close() method. Even then, there is no guarantee that the programmer will call the close() method, so it should be done in a finalize method.
        public void close()
        {
           if (file != null)
           {
              file.close();
              file = null;
           }
        }
        protected void finalize() throws Throwable
        {
           try
           {
              close();
           } 
           finally
           {
              super.finalize();
           }
        }
    
  • The close method is written carefully in case it is called more than once.
  • super.finalize is called to make sure your superclass is also finalized.
  • Train yourself to always do this.

2.8.15 The toString() Method

  • If an object supports a public toString method that takes no parameters and returns a String object, that method is invoked whenever a + or += expression has an object of that type where a String object is expected.
  • All primitive types are implicitly converted to String objects when used in String expressions.

2.8.16 Native Methods

  • Used when you need to manipulate some hardware directly, or execute code not written in Java.
  • Portability and safety of the code are lost.
  • Implemented using an API provided by the people who wrote the virtual machine on the platform where the code will run.
  • The standard API for C programmers is called Java Native Interface (JNI).
  • Other API's are being defined for other languages.