内部类:定义在另一个类中的类。
当描述事物时,事物的内部还有事物,该事物用内部类来描述,因为内部事物在使用外部事物的内容.
使用内部类的原因:

  • 内部类方法可以访问该类定义所在的作用域中的数据,包括私有的数据
  • 内部类可以对同一个包中的其他类隐藏
  • 当想要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较方便

实例6-6:InnerClassTest.java

package innerClass;

import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;

import javax.swing.JOptionPane;
import javax.swing.Timer;

public class innerClassTest 
{   /**
     * @param args
     */
    public static void main(String[] args) 
    {   // TODO 自动生成的方法存根
        TalkingClock clock = new TalkingClock(1000,true);
        clock.start();

        JOptionPane.showMessageDialog(null, "Quit the program???");
        System.exit(0);
    }
}

class TalkingClock
{
    private int interval;
    private boolean be;

    public TalkingClock(int interval, boolean b)
    {
        this.interval = interval;
        this.be = b;
    }

    public void start()
    {
        ActionListener listener = new TimerPrinter();
        Timer t = new Timer(interval, listener);
        t.start();
    }

    public class TimerPrinter implements ActionListener
    {
        public void actionPerformed(ActionEvent event)
        {
            Date now = new Date();
            System.out.println("At the tone , the time is : " + now);
            if(be) Toolkit.getDefaultToolkit().beep();
        }
    }
}

1、使用内部类访问对象状态

  • 内部类可以直接访问外部类中的成员,包括私有的。之所以可以直接访问外部类中的成员,其实是因为内部类中持有了一个外部类的引用,其格式为:外部类名.this
// 其中的 be 是外部类 TalkingClock 的成员变量
if(be) Toolkit.getDefaultToolkit().beep(); // 等价于下句
if(TalkingClock.this.be) Toolkit.getDefaultToolkit().beep();
  • 外部类要访问内部类,必须先创建内部类对象
clock.start();// clock对象调用方法start,在start中创建内部类对象

2、局部内部类

实例6-6中, TimePrinter 这个类名字只在start方法中创建对象时使用一次,这时可以在一个方法中定义局部类,简化代码。

public void start()
{
    class TimerPrinter implements ActionListener
    {
        public void actionPerformed(ActionEvent event)
        {
            ...
        }
    }
    ...
}

注意

  • 局部类不能用 public 或 private 访问说明符进行声明
  • 它的作用域被限定在声明这个局部类的块中
  • 局部类可以对外部世界完全隐藏,即使 TalkingClock 类中的其他成员也不能访问它,除了 start 方法,没有任何方法知道 TimePrinter 类的存在

3、内部类方法访问局部变量

有说是局部类访问的局部变量必须被声明为final,但下面写的程序又没有出现问题。(难道是版本不同的原因???)

class Outer
{
    int x = 3;
    void method(int z)
    {
        int y = 4;
        class Inner 
        {
            int x = 1;
            void function()
            {
                System.out.println(Outer.this.x);// 打印3
                System.out.println(y);// 打印4
                System.out.println(this.x);// 或者 System.out.println(x);打印1 
                System.out.println(z);// 打印6
            }
        }
        new Inner().function();// 创建内部类并调用方法
    }
}
class InnerClassDemo3
{
    public static void main(String[] args) 
    {
        new Outer().method(6);
    }
}

4、匿名内部类

  • 若只创建某内部类的一个对象时,就不必命名,也就是内部类的简写格式
  • 定义的匿名内部类必须是继承一个类或者实现接口
  • 格式:new 父类或者接口() {定义子类的内容}
abstract AbsDemo
{
    abstract void show();   
}

class Outer
{
    int x = 3;
    /*class Inner extends AbsDemo// ①
    {
        void show(){} // ②
    }*/
    public void function()
    {
        //new Inner().show();// ③创建对象并④调用方法
        // 将①-④步放在一起完成
        new AbsDemo()
        {
            void show(){}
            void teyou(){}// 特有的方法
        }.show();
        // 或
        AbsDemo s = new AbsDemo()
        {
            void show(){}
            void teyou(){} //特有的方法
        };
        s.show();
        s.teyou();// 编译失败,因为父类AnsDemo中没有该方法
    }
}

5、静态内部类

  • 当内部类在成员位置上,就可以被成员修饰符所修饰;
    比如
    private:将内部类在外部类中进行封装
    static:内部类就具备static的特性
①、当内部类被static修饰后,只能直接访问外部类中的static成员,出现了访问局限;

②、在外部其他类中,如何直接访问static内部类的非静态成员?
new Outer.Inner().function();

③、在外部其他类中,如何直接访问static内部类的静态成员?
Outer.Inner.function();

注意

  • 当内部类中定义了静态成员,该内部类必须是静态static的
  • 当外部类中静态方法访问内部类时,内部类也必须是静态的
class Outer
{
    private static int x = 3;

    static class Inner
    {
        static void function()// 情况②时未被static修饰;情况③时,被static修饰
        {
            System.out.println("Inner: " + x);// 打印num初始值                   
        }
    }
}

class InnerClassDemo2
{
    public static void main(String[] args) 
    {
        // ①,当内部类Inner及其方法function都未被static修饰时,可如下调用
        // new Outer().new Inner().function();

        // ②
        // new Outer.Inner().function();

        // ③
        Outer.Inner.function();
    }
}

当内部类定义在外部类的成员位置上,而且非私有时,可以在外部其他类中可以直接建立内部类对象;
格式:
外部类名.内部类名 变量名 = 外部类对象.内部类对象
Outer.Inner in = new Outer().new Inner();