Core Java笔记 5.内部类
本章重点:
- 为何使用内部类
- 访问外围类数据
- 内部类的语法规则
- 局部内部类
- 匿名内部类
内部类(inner class)是定义在另一个类中的类。
为何使用内部类
- 内部类方法可以访问外围类的数据,包括私有的数据.
- 内部类可以对同一个包种的其他类隐藏起来.
- 使用anonymous内部类定义回调函数类.
访问外围类数据
示例:
package corejava.inner;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;
/**
* Created by guolong.fan on 15/4/26.
*/
public class InnerClassTest {
public static void main(String[] args) {
TalkingClock clock = new TalkingClock(1000, true);
clock.start();
JOptionPane.showMessageDialog(null, "Quit program?");
System.exit(0);
}
}
class TalkingClock {
public TalkingClock(int interval, boolean beep) {
this.interval = interval;
this.beep = beep;
}
public void start() {
ActionListener listener = new TimePrinter();
Timer timer = new Timer(interval, listener);
timer.start();
}
private int interval;
private boolean beep;
public class TimePrinter implements ActionListener {
@Override
public void actionPerformed(ActionEvent actionEvent) {
System.out.println("At the tone, the time is " + new Date());
if (beep) Toolkit.getDefaultToolkit().beep();
}
}
}
if (beep)...
访问了外围类的私有属性.
内部类是一种编译器现象,与虚拟机无关. 使用 javap 分析编译器如何生成代码的?
javap -private TalkingClock$TimePrinter.class
- 内部类的命名. outclass$innerclass(eg.
TalkingClock$TimePrinter
)- 内部类生成外部类实例的引用(final)+构造器.
public class corejava.inner.TalkingClock$TimePrinter extends java.lang.Object implements java.awt.event.ActionListener{
final corejava.inner.TalkingClock this$0;
public corejava.inner.TalkingClock$TimePrinter(corejava.inner.TalkingClock);
public void actionPerformed(java.awt.event.ActionEvent);
}
- 针对内部类访问了的private fields, 外围类生成 access$ 代码(package权限的getter).
class corejava.inner.TalkingClock extends java.lang.Object{
private int interval;
private boolean beep;
public corejava.inner.TalkingClock(int, boolean);
public void start();
static boolean access$000(corejava.inner.TalkingClock);
}
最终,编译器生成如下代码.
class TalkingClock {
public TalkingClock(int interval, boolean beep) {
this.interval = interval;
this.beep = beep;
}
public void start() {
ActionListener listener = new TimePrinter(this);
Timer timer = new Timer(interval, listener);
timer.start();
}
static boolean access$000(corejava.inner.TalkingClock);
private int interval;
private boolean beep;
public class TimePrinter implements ActionListener {
public TimePrinter(TalkingClock clock) {
outer = clock;
}
@Override
public void actionPerformed(ActionEvent actionEvent) {
System.out.println("At the tone, the time is " + new Date());
if (access$000()) Toolkit.getDefaultToolkit().beep();
}
...
private TalkingClock outer;
}
}
内部类的语法规则
- 外围类的引用. 即上面的 outer 实质是
OuterClass.this
.beep
可以写成TalkingClock.this.beep
. - 生成内部类对象.
outObject.new InnerClass(construction parameters)
.
内部类:
ActionListener listener = this.new TimePrinter();
其他程序中:
TalkingClock jabberer = new TalkingClock(1000, true);
TalkingClock.TimePrinter listener = jabberer.new TimePrinter();
局部内部类
直接定义在方法中.
public class InnerClassTest {
public static void main(String[] args) {
TalkingClock clock = new TalkingClock(1000, true);
clock.start();
JOptionPane.showMessageDialog(null, "Quit program?");
System.exit(0);
}
}
class TalkingClock {
public TalkingClock(int interval, boolean beep) {
this.interval = interval;
this.beep = beep;
}
public void start() {
public class TimePrinter implements ActionListener {
@Override
public void actionPerformed(ActionEvent actionEvent) {
System.out.println("At the tone, the time is " + new Date());
if (beep) Toolkit.getDefaultToolkit().beep();
}
}
ActionListener listener = new TimePrinter();
Timer timer = new Timer(interval, listener);
timer.start();
}
private int interval;
private boolean beep;
}
匿名内部类
package corejava.inner;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;
/**
* Created by guolong.fan on 15/4/26.
*/
public class InnerClassTest {
public static void main(String[] args) {
TalkingClock clock = new TalkingClock(1000, true);
clock.start();
JOptionPane.showMessageDialog(null, "Quit program?");
System.exit(0);
}
}
class TalkingClock {
public TalkingClock(int interval, boolean beep) {
this.interval = interval;
this.beep = beep;
}
public void start() {
ActionListener listener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
System.out.println("At the tone, the time is " + new Date());
if (beep) Toolkit.getDefaultToolkit().beep();
}
};
Timer timer = new Timer(interval, listener);
timer.start();
}
private int interval;
private boolean beep;
}