12. Inner Classes

About this Tutorial –

Objectives –

This course is aimed at object-oriented developers (e.g. C++ or C#) who need to transition into Java. It is also aimed at those learning to program for the first time; the course covers the Java programming constructs and APIs quickly, focussing on the differences between Java and other OO languages.

Audience

This training course is aimed at OO developers who need to transition into Java.

Prerequisites

No previous experience in Java programming is required. But any experience you do have in programming will help. Also no experience in eclipse is required. But again any experience you do have with programming development environments will be a valuable.

Contents

The Java course cover these topics and more:

  • Flow Control: Decision making: if and if-else; The switch statement; Looping: for loops; while loops; do-while loops; for-each style loops; Assertionsv
  • Concurrency: Overview of multithreading; Creating new threads; Object locking; Using wait, notify, and notifyAll
  • Collections: Overview of Java SE collection classes; Generics; Using List-based collection classes; Using Set-based collection classes; Using Map-based collection classes; Collection techniques

Exam Preparation

The Java course will help you prepare for these certifications:

  • Oracle Certified Java Associate – Exam 1Z0-803
  • Oracle Certified Java Professional – Exam 1Z0-804

Download Solutions

HTML tutorial


Overview

Estimated Time – 1.5 Hours

Not what you are looking? Try the next tutorial – File Handling

  1. What is an Inner Class?
    • So far in this course, all of the classes have been defined as “top-level” classes
      • One public class per Java file
      • Plus other non-public classes, if you like
    • Java also allows you to define inner classes
      • Define class(es) inside the scope of another class
  2. Why Define Inner Classes?
    • Firstly, note that most classes ARE NOT inner classes
      • They are top-level classes, as we’ve been using so far on this course
    • One of the benefits of inner classes is that they offer a nested scope:
      • Emphasizes the fact that an inner class really “belongs” to the outer class
      • You can define the inner class as private if you like
    • Another potential benefit is consistency:
      • Several outer classes can have similar inner classes
      • You can give each inner class the same name
  3. Types of Inner Classes
    • There are several types of inner classes:
      • Regular inner classes
      • Method-local inner classes
      • Anonymous inner classes
      • Static nested class
    • We’ll take a look at each approach in the next few sections in this chapter

Lab 1: Regular inner classes

Lab 1: Regular inner classes
  1. Overview
    • Sometimes, when you’re defining a class, you might find yourself wanted to put some behaviour in a separate dedicated class
      • E.g. to define event-handlers in a GUI application
      • You need to define a class that implements the event interface
    • The traditional approach:
      • Define 2 completely separate top-level classes
    • A more encapsulated approach:
      • Define the “subservient” class inside the “main” class
  2. Defining an Inner Class
    • Here’s how you define an inner class:
      public class MyOuter {
      // Members of outer class.
        // Inner class.
        // Can be public, private, protected, or default visibility.
        // Can be abstract, final, or static (see later for discussion on static).
        public class MyInner {
          // Members of inner class.
          // - Can be instance variables and instance methods.
          // - Cannot be static variables or static methods!
        }
      }
    • When you compile this, you get 2 class files:
      • MyOuter.class
      • MyOuter$MyInner.class
  3. Member Access
    • In the outer class:
      • Instance methods can access public members of inner class
      • Instance methods can’t access nonpublic members of inner class
      • Static methods can’t access anything on inner class
    • In the inner class:
      • Can access all the members of the outer class, even if private!
      • Allows inner class to interact with its outer class meaningfully
        public class MyOuter {
          ...
          private int anOuterField;
          public class MyInner {
            ...
            public void anInnerMethod() {
              anOuterField++;
            }
          }
        }
  4. Creating an Inner Object
    • When you have an inner class:
      • The inner object MUST be associated with an outer object
    • So you can’t just create a raw inner object on its own:
      // Error!
      MyInner inner = new MyInner();
    • Instead, you must create the inner object via the context of an outer object
      • Various ways to do this
    • You can define methods in the outer class, with the responsibility of creating inner objects
      public class MyOuter {
       ...
       public MyInner createInner() {
        return new MyInner();
       }
      }
    • Client code:
      • Note the use of MyOuter.MyInner to access inner class name
        // Create an instance of the outer class.
        MyOuter myOuter = new MyOuter();
        // Use the outer object to create an associated inner object.
        MyOuter.MyInner myInner1 = myOuter.createInner();
    • You can create an inner object manually in the client code
      • Using the syntax outerObject.new
        // Create an instance of the outer class.
        MyOuter myOuter = new MyOuter();
        // Manually create an inner object, associated with an outer object.
        MyOuter.MyInner myInner2 = myOuter.new MyInner();
    • You can create an inner object directly after creating the outer object
      • Using the syntax new OuterClass().new InnerClass()
        // Create an outer object and an inner object "at the same time".
        MyOuter.MyInner myInner3 = new MyOuter().new MyInner();
  5. The Meaning of this
    • In an inner class:
      • this means the inner object
      • OuterClassName.this means the associated outer object
    • Example:
      public class MyOuter {
       ...
       private int anOuterField;
       public class MyInner {
        private int anInnerField;
        public void anInnerMethod() {
         this.anInnerField++;     // Or just anInnerField++
         MyOuter.this.anOuterField++; // Or just anOuterField++;
        }
       }
      }
  6. Example
    • For a complete example, see:
      • MyOuterWithInnerClass.java
    • For usage, see:
      • Main.java
      • demoInnerClasses()
Lab
  1. Defining a regular inner classes
    • In the student project, open TableSortDemo.java. This application displays a frame that contains a JTable, which is a Swing data grid component:
    • T12P1

    • Note the following points in the application:
      • If you click a column heading, it sorts the table on that column (it toggles between ascending/descending order)
      • You can edit the last two columns
    • Take a look at the code in TableSortDemo.java. Here’s a brief summary of the important details
      • The TableSortDemo class extends JPanel. In other words, it’s a custom panel that decides how to layout its constituent parts.
      • The TableSortDemo constructor adds a JTable to the panel
      • The JTable object uses a MyTableModel object to define the data, column heading names, and other model-related information for the JTable.
      • The MyTableModel class is currently defined as a top-level class (see the lower half of TableSortDemo.java).
    • Refactor the code, so that MyTableModel is defined as an inner/nested class within the TableSortDemo class. You decide which mechanism to use.
      private static class MyTableModel extends AbstractTableModel {
       ...
      }
    • View code file.

Lab 2: Method-local inner classes

Lab 2: Method-local inner classes
  1. Overview
    • You can define an inner class inside a method
      • The type is only visible inside this method (from its point of definition onwards)
      • The type cannot have a visibility specifier (not even private)
    • The type is completely unknown, outside this method
      • Consequently, the host method is responsible for creating instances
  2. Defining a Method-Local Inner Class
    • Here’s how you define a method-local inner class:
      public class MyOuter {
       
       // Members of outer class.
       // Method in outer class.
       public void someMethod() {
        ...
        // Method-local inner class.
        // Can be abstract or final.
        class MyMethodLocalInner {
         // Members of method-local inner class.
         // - Can be instance variables and instance methods.
         // - Cannot be static variables or static methods!
        }
        ...
       }
      }
    • View code file.
  3. Member Access
    • In the outer class:
      • The host method can access public members of inner class
      • The host method can’t access nonpublic members of inner class
    • In the inner class:
      • Can access all the members of the outer class, even if private!
      • Can access final local variables in host method
      • Can’t access nonfinal local variables in host method
  4. Creating a Method-Local Inner Object
    • The only way to create a method-local inner class:
      • – Is inside the host method
      • – After the inner class definition
        public class MyOuter {
         // Members of outer class.
         // Method in outer class.
         public void someMethod() {
          ...
          class MyMethodLocalInner {
           ...
          }
          // Create instance of inner class.
          MyMethodLocalInner myInner = new MyIMethodLocalnner();
          ...
         }
        }
      • View code file.
  5. Example
    • For a complete example, see:
      • MyOuterWithMethodLocalInnerClass.java
      • hostInner()
    • For usage, see:
      • Main.java
      • demoMethodLocalInnerClasses()

Lab 3: Anonymous inner classes

Lab 3: Anonymous inner classes
  1. Overview
    • An anonymous class is a class that has no name!
      • You just create a one-off instance of the class, within the body of one of your methods
    • Useful for one-off event-listener classes
      • E.g. define an anonymous class that listens for the “click” event for a particular button on a form
      • No need to give the class a name – you only want to use it in one particular place in your code
  2. How to Define an Anonymous Class
    • An anonymous class must either:
      • Inherit from a base class
      • And override some methods (if it likes)
    • Or:
      • Implement an interface
      • And implement all its methods
    • So when you create an instance of an anonymous class, what you are really doing is:
      • Defining a one-off anonymous class (that either inherits from a base class or implements an interface)
      • Creating an instance of that anonymous class
  3. Member Access
    • Exactly the same as for method-local inner classes:
    • In the outer class:
      • The host method can access public members of inner class
      • The host method can’t access nonpublic members of inner class
    • In the inner class:
      • Can access all the members of the outer class, even if private!
      • Can access final local variables in host method
      • Can’t access nonfinal local variables in host method
  4. Extending a Base Class
    • An anonymous inner class that extends a base class:
      public class MyBase {
       ...
      }
      // outer class
      public class MyOuter {
       
       // Members of outer class.
       // Method in outer class.
       public void someMethod() {
        ...
        MyBase obj = new MyBase() {
         // Override base-class methods, as appropriate.
        };
        // Invoke methods on obj, as exposed by base class.
        ...
       }
      }
    • View code file.
  5. Implementing an Interface
    • An anonymous inner class that implements an interface:
      public interface MyInterface {
       ...
      }
      // outer class
      public class MyOuter {
       
       // Members of outer class.
       // Method in outer class.
       public void someMethod() {
        ...
        MyInterface obj = new MyInterface() {
         // Implement interface methods.
        };
        // Invoke methods on obj, as exposed by interface.
        ...
       }
      }
    • View code file.
Lab
  1. Defining several anonymous inner classes
    • In the student project, open DialogBoxExample.java. This application displays a main frame window that allows the user to display thee different types of dialog box:
    • T12P2

    • Take a look at the code in DialogBoxExample.java. Note the following salient details in the code:
      • The DialogBoxExample class implements ActionListener itself. The class has a single actionPerformed() method, which will be invoked to handle button click events for all the buttons.
      • The actionPerformed() method has to determine which button was actually clicked, so that it can decide what to do.
    • This situation is clearly unsatisfactory. It is undesirable to have a single implementation of ActionListener, because we have three buttons and each requires its own specific handler code.
    • Therefore, refactor the DialogBoxExample class so that it doesn’t implement ActionListener directly. Instead define three anonymous inner classes, to handle each button click individually. There are TODO comments in the code, indicating where you need to make your changes.
       // Handle click event on the "info" button.
       ibutton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
         JOptionPane.showMessageDialog(
         frame,
         "This is an information message",
         "My Dialog Box",
         JOptionPane.INFORMATION_MESSAGE);
        }
       });
       // Handle click event on the "warning" button.
       wbutton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
         JOptionPane.showMessageDialog(
         frame,
         "This is a warning message",
         "My Dialog Box",
         JOptionPane.WARNING_MESSAGE);
        }
       });
       // Handle click event on the "error" button.
       ebutton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
         JOptionPane.showMessageDialog(
         frame,
         "This is an error message",
         "My Dialog Box",
         JOptionPane.ERROR_MESSAGE);
        }
       });
    • View code file.

Lab 4: Static nested class

Lab 4: Static nested class
  1. Overview
    • A static nested class:
      • Is defined with the static keyword
    • Just like a normal class, except that it happens to be defined in a nested scope
      • Referenced via syntax OuterClassName.InnerClassName
    • No linkage between outer objects and nested objects
      • No enclosing outer object
      • Different to all the “inner” class techniques in this chapter
  2. Defining a Static Nested Class
    • Here’s how you define a static nested class:
      public class MyOuter {
       // Members of outer class.
       // Static nested class.
       // Can be qualified in any way, just like a normal class.
       public static class MyStaticNested {
        // Members of static nested class.
        // - Can be anything you like!
       }
      }
    • View code file.
  3. Member Access
    • In the outer class:
      • No direct access to members of nested class
      • Think of the nested class as “just another class” (which happens to be defined in a nested scope)
    • In the nested class:
      • No direct access to members of outer class
      • Think of the outer class as “just another class” (which happens to enclose the nested class)
  4. Creating a Static Nested Object
    • You can define methods in the outer class, with the responsibility of creating static nested objects
      public class MyOuter {
       ...
       public MyStaticNested createInner() {
        return new MyStaticNested();
       }
      }
    • View code file.
    • Client code:
      • Note the use of syntax MyOuter.MyStaticNested
        // Create an instance of the outer class.
        MyOuter myOuter = new MyOuter();
        // Use the outer object to create an (unrelated) instance of static nested class.
        MyOuter.MyStaticNested myNested1 = myOuter.createNested();
    • You can create a nested object manually in the client code
      • Remember, no need for enclosing outer object
        // Manually create instance of static nested class (no associated outer object).
        MyOuter.MyStaticNested myNested2 = new MyOuter.MyStaticNested();
  5. Example
    • For a complete example, see:
      • MyOuterWithStaticNestedClass.java
    • For usage, see:
      • Main.java
      • demoStaticNestedClasses()

 

Well done. You have completed the tutorial in the Java course. The next tutorial is

13. File Handling


Back to beginning
Copyright © 2016 TalkIT®






If you liked this post, please comment with your suggestions to help others.
If you would like to see more content like this in the future, please fill-in our quick survey.
Scroll to Top