The Java Explorer Back | TOC | Next

<Core><Intermediate><Advanced>
Overview | Packages | Class Internals | Collections | I-O | Network | Database 

Like any object-oriented language worth its salt, Java wraps the data and the operations to manipulate that data into a class. A class is therefore the smallest free-standing unit in Java. 

Encapsulation
Class encapsulates data and methods that operate on the data. The data may be a scalar unit like a number or a string; it may also be a composite like a collection object such as a Vector or Hashtable. A good design does not expose the internals of a class: it keeps its data members private, and exposes methods that return processed data, but rarely the data member itself. 

Java specifies access modifiers on data and methods via the reserved words: private, protected and public. The modifier indicates the accessibility of data or method of a class. The protected modifier ensures that the data or method it modifies is accessible only to the inherited derived classes in the same inheritance chain. To make a method available to classes outside the class in which it is defined, use public modifier. To use public modifier to data elements of a class is to invite disaster: it undermines the basic tenet of data encapsulation. Use private instead, or protected to allow accessibility to derived classes only.

public class DataHider {
    private String data;
    public String getData() {
         String processedData;
         // process data
         return processedData;
   }
}

The data string is held privately, and is returned only after necessary processing via a publicly declared method. This way the user of the class is unaware of how data is stored inside the class, but is concerned only with the returned data. If you declare a class as public, then it must be saved in a file of the same name.

To declare data members and operations without any access modifiers is to provide a package level access, meaning Java denotes what is called a default package, and allows indiscriminate access. All non-trivial programs provide proper access levels.

Inheritance
While the word class is a typical OO term, Java reserves two keywords Class and Interface to differentiate a  class functionality. An interface is a class that has no data members, but only method declarations, and may or may not have defined constants. A class on the other hand may be an abstract class with partial functionality or a concrete class with full functionality. A concrete class may thus be a class that implements an interface or a derived class that provides the inherited functionality by extending an abstract class.

Classes form a hierarchy of an inheritance chain. While the lower classes provide increasing specialization, the upper level classes provide increasingly common functionality. Java allows only single inheritance, meaning that a class may have no more than one parent. The functionality you seek through multiple inheritance may be achieved through the use of interface. The inheritance mechanism has a created a few synonymous terms to refer to classes in the inheritance relationship: 

Inheritance is the cornerstone of OO programming: it provides code re-use. You code a functionality in one class and re-use it in all its sub-classes. It also enables code partitioning in which you separate common functionality from specialized functionality. It provides extensibility, too, since you can derive new classes from the old ones with brand new functionality. This feature is largely responsible for the phenomenal growth of the Java language, without sacrificing the core functionality.

Inner class
A class may be embedded in another class. The embedded class may have a name, or it may be an anonymous inner class. The container class may or may not expose the functionality of embedded classes to the outside world. Inner classes are often used in Java programs. Event delivery in Java is often coded as inner classes.

Listing 1:
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;

public class CloseableJFrame extends JFrame {
    public CloseableJFrame() {
        super("Closeable JFrame");
        setSize(300,150);
        setVisible(true);
        addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent evt) {
                          System.exit(0);
               }
       });
    }
    public static void main(String[] args) {
       new CloseableJFrame();
   }
}

WindowAdapter is an anonymous inner class in the above example. It is a built-in class from the awt.event package, so we could instantiate it here and implement the windowClosing event. Inner classes are not limited to Java events; you may write your own. 

Class Reflection
You may reflect upon a class using the reflection mechanism. You reflect on a class in order to know its internals. The reflection API - classes in the java.lang and the java.lang.reflect packages - provide the means to reflect or introspect a class that is currently running in the Java Virtual Machine.

Why Reflection?
What do you want to know the class internals for? First, let us see what reflection or introspection of a class reveal to us. As we said before, introspection reveals the internals of a class, such as the names of the class fields, methods, and constructors.

If you wanted to write a class browser, then you would certainly need a way to inspect the classes at run time. You would probably want to keep a log or provide an explorer view of classes.

If you are developing an IDE for Java, you would give your users a debug option. Here again, you will need to look into the class internals.

How do I use the Reflection API?
The Class class represents the class reflected - does it sound like Voodoo?

We will see it by example. Let us apply some of the reflection API to Listing 1 above. Using java.lang.reflect package, you can retrieve information about a class at runtime. First, you create a class Class object for the target class in question. With the Class object so obtained, you gather information about the target's constructors, methods, fields and so on.

Listing 2:
import java.lang.reflect.*; // import the reflection package

public class ReflectCloseableJFrame {

public ReflectCloseableJFrame() {

  // Get an instance of the Target class
  CloseableJFrame frame = new CloseableJFrame();

  // Get the Class object from the target class instance
  Class cFrame = frame.getClass();

  // Get the name of the class
  String frameName = cFrame.getName();
  System.out.println("Target Class Name: "+frameName);

  // Get the parent super class from the target class instance
  Class cFrameParent = cFrame.getSuperclass();

  // Get the name of the parent class
  String frameParentName = cFrameParent.getName();
  System.out.println("Target's Parent Class Name: "+frameParentName);

  // Get target class's modifier
  System.out.print("Class Modifier: ");
  int modifiers = cFrame.getModifiers();
  if (Modifier.isPublic(modifiers))
    System.out.println("public");
  if (Modifier.isAbstract(modifiers))
    System.out.println("abstract");
 if (Modifier.isFinal(modifiers))
    System.out.println("final");

  // Get the constructors of the target class
  Constructor[] ctors = cFrame.getConstructors();
  for (int i = 0; i < ctors.length; i++) {
     System.out.print("Constructor: "+ctors[i].toString());
  }
}

public static void main(String[] args) {
  new ReflectCloseableJFrame();
}

}

The output is:
Target Class Name: CloseableJFrame
Target's Parent Class Name: javax.swing.JFrame
Class Modifier: public
Constructor: public CloseableJFrame()

The reflection package makes it quite simple to perform a kind of biopsy on a running instance of a class without modifying it in any way. You might think of it as a non-destructive examination of objects at run time.