Inner classes

 

Overview

For convenience, Java permits a class to be defined inside another class. Such classes are called "inner classes". 

 

An inner class

class classname1 {
 
Outer class data and methods...
  class classname2 {
   
Inner class data and methods...
  }
}

Example 1: The following program contains a public, instance inner class (recall that instance features of a class can access other instance features or static features of the class).

public class App {

  // A class (static) variable.

  private static int x = 2;

  // An instance variable.

  private int y = 3;

  // An instance inner class.

  public class Inner {
    public void showProduct() {
      System.out.println("Product is " + (x * y));
    }
  }

  // The starting point for the application.

  public static void main(String[] args) {

    // Create an inner class object and call its showProduct() method.

    Inner in = new App().new Inner();
    in.showProduct();
  }
}

Notes:

  1. When an inner class is non-static, as in this example, an outer class object must be instantiated in order to reference it.

  2. As an instance feature of the outer class, an instance inner class may reference any instance or class feature of the enclosing class.

  3. Because the inner class is public, an object of the class can be instantiated from outside the enclosing class by coding a statement such as:

App.Inner x = new App().new Inner();

where the object type is the qualified name of the outer and inner class names.

Example 2: The following program contains a public, static inner class (recall that static features can only access other static features of a class).

public class App {

  // A class (static) variable.

  private
static int x = 2;

  // An instance variable.

  private int y = 3;

  // A static inner class.

  public static class Inner {
    public static void showX() {
      System.out.println("x is " + x);
    }
  }

  // The starting point for the application.

  public static void main(String[] args) {

    // Call the static method of the inner class.

    Inner.showX();
  }
}

Notes:

  1. Like all static features, a static inner class can only access static features of its enclosing class.

  2. Because the inner class is static, its features are available without instantiating an object.

  3. To call the showX() method from outside the outer class, one could code:

App.Inner.showX();

Example: The following program contains an inner class defined within an instance method.

public class App {

  // A class (static) variable.

  private static int x = 2;

  // An instance variable.

  private int y = 3;

  // The starting point for the application.

  public static void main(String[] args) {

    // Construct an object of the outer class and call its
    // showSum() method.

    App myApp = new App();
    myApp.showSum(4);
  }

  // This instance method uses an inner class to display the sum of
  // several integers. One parameter is received as a constant.

  public void showSum(
final int w) {

    // A method local constant.

   
final int z = 5;

    // This inner class contains a method to display the sum of several
    // integers that are within its scope.

    class Inner {
      public void show() {
        System.out.println("Sum is " + (w + x + y + z));
      }
    }

    // Construct an object of the inner class and call its show() method.

    Inner myInner = new Inner();
    myInner.show();
  }
}

Notes:

  1. If w and z aren't final, this code will not compile. This prevents the Inner object from outliving its data. Constants do not reside in the memory "stack" like method local variables and are not automatically deleted when the method ends.

  2. A class defined within a method may NOT have an access modifier (public, protected, or private). The access is that of the enclosing method. If an access modifier is coded, a compile error will occur.

  3. If showSum() had been declared a class (static) method, variable y would not be accessible to class Inner (because a static feature can't access an instance feature of a class).

 

Anonymous inner classes

new classname () {
 
Statements in the class body...
}

where the code that precedes the opening brace is the constructor call.

import java.awt.*;
import java.awt.event.*;

// This class extends Frame to inherit the features of a frame window.

public class App extends Frame {

  // Object references.

  Button b;
  Label msg;

  // Application processing starts here.

  public static void main(String[] args) {
    App myWindow = new App("Java does Windows");
    myWindow.setSize(250, 200);
    myWindow.setVisible(true);
  }

  // This is the class constructor. It recieves the window's title
  // as a parameter.

  public App(String title) {
    super(title);
    addWindowListener(
      new WindowAdapter() {
        public void windowClosing(WindowEvent e) {
          dispose();
          System.exit(0);
        }
      }
    );
    msg = new Label("");
    msg.setForeground(Color.red);
    msg.setFont(new Font("Serif", Font.BOLD + Font.ITALIC, 24));
    msg.setAlignment(Label.CENTER);
    add(msg, BorderLayout.CENTER);
    b = new Button("Click Here");
    b.addActionListener(
      new ActionListener () {
        public void actionPerformed(ActionEvent e) {
          msg.setText("Hello World!");
        }
      }
    );
    add(b, BorderLayout.SOUTH);
  }
}

Note: You are not expected to understand the details of this program. It is a topic for advanced Java programming.

 

More information

Java ranch has an excellent "campfire story" relating to this lesson. Be sure to read Getting in Touch With Your Inner Class.

 

Lab exercise for Ferris students

E-mail your answers to this assignment no later than the due date listed in the class schedule.

 

Review questions

  1. Based upon this code, which one of the following would result in the message "hello" being displayed on the console when run from another class? 

public class Outer {
  public class Inner {
    public void hello() {
      System.out.println("hello");
    }
  }
}

  1. Inner x = new Outer().new Inner();
    x.hello();

  2. Inner x = new Outer. Inner();
    x.hello();

  3. Outer.Inner x = new Outer().new Inner();
    x.hello();

  4. Outer.Inner x = new Outer. Inner();
    x.hello();

  5. Inner x = new Inner();
    x.hello();

  1. True or False: If coded in a file named Out.java, the following statements will compile successfully.

public class Out {
  public void outMethod() {
    public class In {
      public void inMethod() {
      }
    }
  }
}

  1. True

  2. False

  1. Consider the following class definition:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Outside {
  public byte a = 1;
  private short b = 2;
  public void outsideMethod(int c) {
    int d = 9;
    final long e = 123456;
    class Inside {
      private void insideMethod() {
        
      }
    }
  }
}

Which variables or constants may be referenced correctly at line 9?  (choose three)

  1. a

  2. b

  3. c

  4. d

  5. e

  1. What will happen when an attempt is made to compile and execute the following program? The line numbers are for reference purposes only.

1
2
3
4
5
6
7
8
9
10
11
public class App {
  public static class Inner {
    public void howdy() {
      System.out.println("howdy");
    }
  }
  public static void main(String[] args) {
    Inner x = new Inner();
    x.howdy();
  }
}
  1. a compile error will occur at line 2

  2. a compile error will occur at line 8

  3. compilation will succeed but a runtime error will occur at line 9

  4. the program will compile and execute to display "howdy"

  5. the program will compile and execute but nothing will be displayed