内部类总结
内部类是java中比较复杂的内容,接下来进行一些细节总结:
内部类(inner class)是定义在一个类中的类,这种技巧有什么好处呢?
- 内部类可以访问外部类中的数据,包括私有数据
- 内部类对于包中其它类来说是隐藏的
- 当想要定义一个回调(callback)函数时,可以使用匿名内部类,这样更为便捷
(回调函数:可以指出一个特定事件发生时应该采取的动作.例如在按下鼠标或选择某个菜单时应该采取什么行动)
1.使用内部类访问对象状态:
public class TalkingClock { private int interval; private boolean beep; public TalkingClock(int interval, boolean beep) { . . . } public void start() { . . . } public class TimePrinter implements ActionListener //内部类 { . . . } }
内部类的详细代码:
public class TimePrinter implements ActionListener { public void actionPerformed(ActionEvent event) { System.out.println("At the tone, the time is " + new Date()); if (beep) Toolkit.getDefaultToolkit().beep(); } }
可以发现,在内部类中的beep是外部类中的变量,这样的引用是如何做到的呢?
事实上,是通过这样一种方式调用的 if (outer.beep) Toolkit.getDefaultToolkit().beep();
但是,outer并不是java中的关键字,可以看到,内部类并没有构造器,所以编译器隐式地给内部类了一个构造器:
public TimePrinter(TalkingClock clock) { outer = clock; }
2.内部类的特殊语法规则:
事实上,内部类对外部类引用的语法还要复杂一点:outerclass.this表示外部类数据的引用,如:
public class TimePrinter implements ActionListener { public void actionPerformed(ActionEvent event) { System.out.println("At the tone, the time is " + new Date()); if (outer.this.beep) Toolkit.getDefaultToolkit().beep(); } }
细节规则:
- 内部类中所有的静态域都必须是final,因为对于一个外部类的实例,我们希望它都只有唯一一个内部类实例
- 内部类不能有静态方法
3.局部内部类:
如果内部类只在外部类的一个方法中调用了一次,我们可以采取使用局部内部类来简化代码:
public void start() { class TimePrinter implements ActionListener { public void actionPerformed(ActionEvent event) { System.out.println("At the tone, the time is " + new Date()); if (beep) Toolkit.getDefaultToolkit().beep(); } } ActionListener listener = new TimePrinter(); Timer t = new Timer(interval, listener); t.start(); }
局部内部类不能用public和private来声明,它的作用域只限于在这个局部的块中
局部内部类的另一个优点是对外部世界完全隐蔽,即除了start()方法外,没有任何方法知道TimePrinter类
细节规则:
- 当局部内部类访问局部变量时,必须为final
int counter = 0; Date[] dates = new Date[100]; for (int i = 0; i < dates.length; i++) dates[i] = new Date() { public int compareTo(Date other) { counter++; //错误 return super.compareTo(other); } }; Arrays.sort(dates); System.out.println(counter + " comparisons.");
4.匿名内部类:
语法格式:
new SuperType(construction parameters) { inner class methods and data }
例:
public void start(int interval, boolean beep) { ActionListener listener = new ActionListener() { public void actionPerformed(ActionEvent event) { System.out.println("At the tone, the time is " + new Date()); if (beep) Toolkit.getDefaultToolkit().beep(); } }; Timer t = new Timer(interval, listener); t.start(); }
细节规则:
- 由于构造器的名字必须与类相同,但是匿名内部类没有名字,所以匿名内部类没有构造器