java(6)内部类基础
2015-11-18 23:10
465 查看
【0】README
0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 java内部类 的基础知识;【1】内部类相关
1.1)为什么要使用 内部类?(Reason)R1)内部类可以访问该类定义所在的作用域中的数据, 包括私有数据;
R2)内部类可以对同一个包中的其他类隐藏起来;
R3)当想要定义一个回调函数且不想编写大量代码时, 使用匿名内部类比较方便;
1.2)嵌套类有两个好处(Merit):
M1)命名控制+访问控制;
M2)需要注意的是, Link类位于 LinkedList 类 的私有部分, 因此,Link对其他的代码均不可见;鉴于此情况,可以将Link的数据域设计为 public, 它仍然是安全的,因为这些数据域只能被 LinkedList类中的方法访问, 而不会暴露给其他的代码;
【2】使用内部类访问对象状态
2.1)看个荔枝:构造一个语音时钟需要两个参数:发布通告的时间间隔 + 开关铃声的标志:2.2)需要注意: 这里的 TimePrinter 位于 TalkingClock 的内部, 并不意味着 每个 TalkingClock 都有一个 TimePrinter 实例域;
2.3)看更加详细的 TimePrinter(值得注意的是,actionPerformed 方法在发出铃声前检查了 beep 标志):
这是因为, 内部类既可以访问自身的数据域,也可以访问创建它的外围类对象的数据域(干货);
2.4)为了能够运行这个程序, 内部类的对象有一个隐式引用, 它指向了 创建它的外部类对象(内部类对象拥有一个对外围类对象 的 引用):
2.5)外围类的引用在构造器中设置。编译器修改了所有的内部类的构造器, 添加了一个外围类引用的参数, 因为 TimePrinter 类没有定义构造器, 所以编译器为这个类生成了一个默认构造器;
2.6)当在 start方法中创建了 TimerPrinter对象后, 编译器就会将 this 引用传递给当前的语音时钟构造器:
ActionListener listener = new TimePrinter(this); // parameter automatically added
Annotation) TimerPrinter 类声明为私有的, 这样一来, 只有 TalkingClock的方法才能够构造 TimePrinter对象, 只有内部类可以是私有类,而常规类只可以具有包可见性, 或公有可见性;
package com.corejava.chapter6_2; import java.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.*; import javax.swing.Timer; /** * This program demonstrates the use of inner classes. * @version 1.10 2004-02-27 * @author Cay Horstmann */ public class InnerClassTest { public static void main(String[] args) { TalkingClock clock = new TalkingClock(1000, true); clock.start(); // keep program running until user selects "Ok" JOptionPane.showMessageDialog(null, "Quit program?"); System.exit(0); } } /** * A clock that prints the time in regular intervals. */ class TalkingClock { private int interval; private boolean beep; /** * Constructs a talking clock * @param interval the interval between messages (in milliseconds) * @param beep true if the clock should beep */ public TalkingClock(int interval, boolean beep) { this.interval = interval; this.beep = beep; } /** * Starts the clock. */ public void start() { ActionListener listener = new TimePrinter(); Timer t = new Timer(interval, listener); t.start(); } private class TimePrinter implements ActionListener { public void actionPerformed(ActionEvent event) { Date now = new Date(); System.out.println("At the tone, the time is " + now); if (beep) Toolkit.getDefaultToolkit().beep(); } } }
【3】内部类的特殊语法规则
3.1)使用外围类引用的正规语法还要复杂一些, 表达式 OuterClass.this 表示外围类的引用;如:public void actionPerformed(ActionEvent event) { if(TalkingClock.this.beep) Tookit.getDefaultToolkit().beep(); }
反过来,可以采用下列语法格式更加明确地编写内部对象的构造器:(下面代码中的this是外部类调用start方法的时候,传了一个外部类本身的this引用,this.new == TalkingClock.new TimePrinter)
outerObject.new InnerClass(construction parameters) 如, ActionListener listener = this.new TimePrinter();
上面的代码中: 最新构造的 TimePrinter 对象 的外围类引用被设置为创建内部类对象的方法中的this引用;这是一种最常见的 情况;
3.2)可以显式地命名将外围类引用设置为其他的对象:如, 如果TimerPrinter 是一个公有内部类,对于任意的语音时钟都可以构造一个 TimePrinter:
TalkingClock jabberer = new TalkingClock(1000, true); TalkingClock.TimePrinter listener = jabberer.new TimerPrinter();
Attention)需要注意, 在外部类的作用域之外,可以这样引用内部类:
OuterClass.InnerClass
【4】内部类是否有用、必要和安全
4.1)内部类是一种编译器现象, 与虚拟机无关:编译器将会把内部类翻译为用 $ 分隔外部类名和内部类名的常规类文件, 而虚拟机则对此一无所知;如, 在 TalkingClock 类内部的 TimePrinter 类将被翻译成类文件 TalkingClock\$TimePrinter.class;
4.2)可以看到: 编译器为了引用外围类,生成了一个附加的实例域 this$0;
4.3)内部类可以访问外围类的私有数据, 而常规类则不行:可见, 由于内部类拥有访问特权, 所以与常规类比较起来功能更加强大;
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树
- [原创]java局域网聊天系统