Java学习笔记---内部类

mac2024-11-06  45

使用内部类的优点

内部类是定义在另一个类中的类,使用内部类主要有以下优点

①内部类方法可以访问该类的定义所在的作用域中的数据,包括私有的数据 ②内部类可以对同一个包中的其他类隐藏其阿里 ③使用匿名内部类比较便捷

使用内部类访问对象状态

package com.javatest; 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 TimerTest { public static void main(String[] agrs) { InnerClassTest t = new InnerClassTest(1000 ); t.go(); JOptionPane.showMessageDialog(null, "Quit program?"); System.exit(0); } } class InnerClassTest { private int interval; public InnerClassTest(int interval ) { this.interval = interval; } public void go() { Timer timer = new Timer(interval , new listeneraction()); timer.start(); } private class listeneraction implements ActionListener{ @Override public void actionPerformed(ActionEvent e) { System.out.println("The time is " + new Date()); } } }

listeneraction是一个内部类,这个类实现了接口ActionListener中的actionPerformed方法,然后类listeneraction作为实例传入Timer的构造器中,事实上,内部类listeneraction可以访问InnerClassTest 类的实例域,一个内部类可以访问自身的的数据域,也可以访问创建它的外围类对象的数据域。 下面来看这是如何实现,在一个内部类中访问外部类的数据域,为了可以运行这个程序,内部类的对象总是有一个隐式引用,我们假设为Outer(Outer不是java的关键字)。 这个引用在内部类的定义中是不可见的。

局部内部类

public void go() { class listeneraction implements ActionListener { @Override public void actionPerformed(ActionEvent e) { System.out.println("The time is " + new Date()); if(beep){ Toolkit.getDefaultToolkit().beep(); } } Timer timer = new Timer(interval , new listeneraction()); timer.start(); }

上面的例子就是一个局部内部类的例子,注意:局部类不能使用public或者private来修饰。它的作用域已经被限定在声明这个局部类的块中。除了,go方法外,没有任何方法知道listeneraction 的存在 。

局部内部类还有一个优点,它不仅可以访问包含它们的外部类,还可以访问局部变量 看下面的例子

public void go(int interval , boolean beep) { class listeneraction implements ActionListener { @Override public void actionPerformed(ActionEvent e) { System.out.println("The time is " + new Date()); if(beep){ Toolkit.getDefaultToolkit().beep(); } } } Timer timer = new Timer(interval , new listeneraction()); timer.start(); }

将类InnerClassTest构造器的参数,interval,beep移动到go方法中。这看起来很正常,类listeneraction 访问beep变量似乎是合情合理的事情,我们思考一下整个的控制流程:调用go方法—>调用内部类listeneraction 的构造器—>将实例化的类对象listeneraction传入Timer构造器,调用stsrt方法,beep变量被释放—>最后,actionPerformed方法执行 if(beep)。从上面的流程中,要使actionPerformed方法可以正常工作,可以看出类listeneraction 在beep域被释放之前用go方法的局部变量进行了备份! 编译器必须检测对局部变量的访问,为每一个变量建立相应的数据域,并将局部变量拷贝到构造器中,以便将这些数据域初始化为局部变量的副本。局部类的方法只可以引用定义为final的局部变量,这样才使得局部变量与在局部类内创建的拷贝的变量保持一致

匿名内部类

假如只创建这个类的一个对象,就不用命名了,这就是匿名内部类。

public void go(int interval , boolean beep) { Timer timer = new Timer(interval, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.out.println("The time is " + new Date()); if (beep) { Toolkit.getDefaultToolkit().beep(); } } } ); timer.start(); }

创建一个实现ActionListener接口的类的新对象,需要实现的方法actionPerformed定义在{}中。匿名类没有类名,所以不能有构造器。如今,使用匿名内部类还是使用Lambda表达式。

最新回复(0)