Java Nested Classes

In Java you can define a class inside an other class.

A class can be nested:

  • inside another class,
  • or inside a method

Nest a class inside a class

When a class is declared inside another class, the nested class' access modifier can be public, private or package(default).

public class OuterClass
{
   private String outerInstanceVar;

   public class InnerClass
   {
      public void printVars()
      {
         System.out.println( "Print Outer Class Instance Var.:" + outerInstanceVar);
      }
   } 
}

The inner class has access to the enclosing class instance's variables and methods, even private ones, as seen above. This makes it very different from the nested class in C++, which are equivalent to the "static" inner classes, see below.

An inner object has a reference to the outer object. The nested object can only be created with a reference to the 'outer' object. See below.

public void testInner()
{
    ...
    OuterClass outer = new OuterClass();
    OuterClass.InnerClass inner = outer.new OuterClass.InnerClass();	
    ...
}

(When in a non-static method of the outer class, you can directly use new InnerClass(), since the class instance is implied to be this.)

You can directly access the reference to the outer object from within an inner class with the syntax OuterClass.this; although this is usually unnecessary because you already have access to its fields and methods.

Inner classes compile to separate ".class" bytecode files, usually with the name of the enclosing class, followed by a "$", followed by the name of the inner class. So for example, the above inner class would typically be compiled to a file named "OuterClass$InnerClass.class".

Static inner class

An inner class can be declared static. A static inner class has no enclosing instance, and therefore cannot access instance variables and methods of the outer class. You do not specify an instance when creating a static inner class. This is equivalent to the inner classes in C++.

Nest a class inside a method

These inner classes, also called local classes, cannot have access modifiers, like local variables, since the class is 'private' to the method. The inner class can be only abstract or final.

public class OuterClass
{
   public void method()
   {
      class InnerClass
      {
 
      } 
   }
}

In addition to instance variables of the enclosing class, local classes can also access local variables of the enclosing method, but only ones that are declared final. This is because the local class instance might outlive the invocation of the method, and so needs its own copy of the variable. To avoid problems with having two different copies of a mutable variable with the same name in the same scope, it is required to be final, so it cannot be changed.

Anonymous Classes

In Java a class definition and its instantiation can be combined into a single step. By doing that the class does not require a name. Those classes are called anonymous classes. An anonymous class can be defined and instantiated in contexts where a reference can be used, and it is a nested class to an existing class. Anonymous class is a special case of the local class to a method, above; and hence they also can use final local variables of the enclosing method.

Anonymous classes are most useful to subclass and upcast to an 'Adapter Class' or to an interface.

public interface ActionListener
{
    public void click();
}
...
ActionListener clk = new ActionListener() 
    {
        public void click()
        {
            // --- implementation of the click event ---
            ...
            return;
        }
    };

In the above example the class that implements the ActionListener is anonymous. The class is defined where it is instantiated.

The above code is harder to read than if the class explicitly defined, so why use it? If many implementations are needed for an interface and those classes are used only in one particular place, using anonymous class makes sense.

The following example uses anonymous class to implement an action listener.

import java.awt.*;
import java.awt.event.*;
import java.io.Serializable;
class MyApp implements Serializable
{
   BigObjectThatShouldNotBeSerializedWithAButton bigOne;
   Button aButton = new Button(); 
   MyApp()
   {
       aButton.addActionListener( new ActionListener()
           {
               public void actionPerformed(ActionEvent e)
               {
                   System.out.println("Hello There");
               }
           }
       );
   }
}

The following example does the same thing, but it names the class that implements the action listener.

import java.awt.*;
import java.awt.event.*;
import java.io.Serializable;
class MyApp implements Serializable
{
   BigObjectThatShouldNotBeSerializedWithAButton bigOne;
   Button aButton = new Button();
   // --- Nested class to implement the action listener ---
   class MyActionListener implements ActionListener
   {
       public void actionPerformed(ActionEvent e)
       {
           System.out.println("Hello There");
       }
   }
   MyApp()
   {
       aButton.addActionListener( new MyActionListener() );
   }
}

Using anonymous classes is especially preferable when you intend to use many different classes that each implement the same Interface.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值