在 java 的 code 过程中,常会面对内部类的使用,在此根据自己理解,对内部类做一总结,方便学习。高手轻拍。
内部类顾名思义,就是定义在其它类内部的类,在这里内部类有两种区分:在其它类的内部;在其它类的方法的内部。
内部类使用主要基于以下三点:
1)通过内部类可以直接访问该类所定义的作用域中的数据,包括 private 数据。
2)通过添加 private 访问符或 local inner class,将内部类对同一包中其它类隐藏起来。
3)定义回调函数。
一:inner class
格式
class A {
class B {
....
}
}
例子:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;
import static java.lang.System.out;
public class InnerClassTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
TalkingClock clock = new TalkingClock(1000, true);
clock.start();
TalkingClock.TimerPrinter t = clock.new TimerPrinter();
JOptionPane.showMessageDialog(null, "Quit program?");
System.exit(0);
}
}
/**
* descr:inner class
* */
class TalkingClock {
public TalkingClock(int interval, boolean beep) {
this.interval = interval;
this.beep = beep;
}
/**
* descr:inner class. if the inner class with private,
* */
public void start() {
ActionListener listener = this.new TimerPrinter();
Timer t = new Timer(this.interval, listener);
t.start();
/*
TalkingClockII t = new TalkingClockII();
t.start(1000, true);
*/
}
/**
* descr:if inner class declared with private, the inner class is only used
* by outter class. any class couldn't used it,even if it is in the same
* package.
* */
class TimerPrinter implements ActionListener {
public TimerPrinter() {
}
public TimerPrinter(int interval, boolean beep) {
this.beep = beep;
}
public void actionPerformed(ActionEvent ev) {
Date now = new Date();
System.out.println("At the tone, the time is " + now);
if (TalkingClock.this.beep) {
Toolkit.getDefaultToolkit().beep();
}
}
private boolean beep;
}
private int interval;
private boolean beep;
}
可以看到 TimerPrinter 作为内部类。当 access specifier 为 default 时,TimerPrinter 为包访问权限,为 public 时,为公共访问权限,但 TimerPrinter 要根据 Outter 类来决定是否可被外包函数访问。当为 private 时,只可被 Outter 访问。
二:local inner class
格式:
class A{
method(para1, para2,...) {
class B{
...
}
}
}
例子:
package ch06;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;
import javax.swing.Timer;
/**
* @copyright 2023-2022
* @package ch06
* @file TalkingClock01.java
* @date 2023-06-04 13:38
* @author qiao wei
* @version 1.0
* @brief Local inner class. Local inner class is defined in method of Outer class, it is not
* allowed modifying the method parameter in local inner class.
* @history
*/
public class TalkingClock01 {
public TalkingClock01() {
flag = false;
}
/**
* @class TalkingClock01
* @date 2023-06-04 13:36
* @author qiao wei
* @version 1.0
* @brief Start method
* @param interval Time interval.
* @param beep flag for voice.
* @return
* @throws
*/
public void start(int interval, boolean beep) {
/**
* @copyright 2023-2022
* @package ch06
* @file TalkingClock01.java
* @date 2023-06-04 13:20
* @author qiao wei
* @version 1.0
* @brief Local inner class. inner class is defined in method.
* @history
*/
class TimePrinter01 implements ActionListener {
public TimePrinter01() {}
@Override
public void actionPerformed(ActionEvent event) {
Date now = new Date();
System.out.println("At the tone, the time is " + now);
// Reset outer class field is allowed.
flag = true;
if (beep) {
Toolkit.getDefaultToolkit().beep();
}
}
}
ActionListener listener = new TimePrinter01();
Timer timer = new Timer(interval, listener);
/**
* After the start function, the beep parameter is no longer exists while timer is always runing
* if beep is true.
*/
timer.start();
}
private boolean flag;
}
TimePrinter01作为局部内部类,不能用 private、public、protected 等修饰符来生命,local inner class 的作用域被限定到生命该局部类的块中,这样使得TimePrinter01类完全对外界隐藏,只有包含它的 start 方法知道其存在,即使是 Outter class TalkingClock01都不知道TimePrinter01的存在。
注意事项:局部内部类调用方法的参数时,不能修改参数值。调用外部类的实例变量时,可以修改变量值。匿名内部类同样要注意。
三:匿名内部类
格式:
class A {
method1() {
class B = new B(para1, para2,...) {
...
};
}
method2() {
interface C = new C() {
....
};
}
}
例子:
class TalkingClockIII {
public void runImplements() {
IWrite w = new IWrite() {
public void write(boolean flag) {
if (flag) {
out.println("anonymous inner class.");
}
}
};
w.write(true);
}
public void runExtends(boolean flag) {
TestWrite t = new TestWrite(flag) {
public void test() {
out.println("flag is " + flag);
}
};
t.test();
}
}
匿名内部类中,如果匿名类继承的是 interface,则不可带参数;如果继承的是 class,则可带参数。