java 内部类
来源:互联网 发布:wps数据透视表高级技巧 编辑:程序博客网 时间:2024/06/15 02:21
内部类(inner class)是定义在另一个类中的类。为什么要使用内部类呢?主要原因有以下三点:
1、内部类方法可以访问该类定义所在的作用于中的数据,包括私有的数据
2、内部类可以对同一个包中的其他类隐藏起来
3、当想要定义一个回调函数且不想编写大量代码时,使用匿名(annoymous)内部类比较便捷
我们将这个比较复杂的内容分几部分介绍
1、给出一个简单的内部类,他将访问外围类的实例域
2、给出内部类的特殊语法规则
3、领略一下内部类的内部,探讨一下如何将其转换为常规类
4、讨论局部内部类,他可以访问外围作用域中的局部变量
5、介绍匿名内部类,说明在java有lambda表达式之前用于实现回调的基本方法
6、介绍如何将静态内部类嵌套在辅助类中
嵌套是一种类之间的关系,二是不是对象之间的关系。一个LinkedList对象并不包含Iterator类型或者Link类型的子对象。
嵌套类有两个好处:命名控制和访问控制。由于名字Iterator嵌套在LinkedList类的内部,所以在外部命名为LinkedList::Iterator,这样就不会与其他名为Iterator的类发生冲突。在java中这个并不重要,因为java包已经提供了相同的命名控制。需要注意的是,Link类位于LinkedList类的私有部分,因此,Link对其他的代码均不可见。鉴于此种情况,可以将Link的数据与设计为公有的,他仍然是安全的。这些数据域只能被LinkedList类中的方法访问,而不会暴露给其他的代码。在java中,只有内部类可以实现这样的控制。
然而,java内部类还有另外一个功能, 这使得它比C++的嵌套类更加丰富,用途更加广泛。内部类的对象有一个隐式调用,他引用了实例化该内部对象的外围类对象。通过这个指针,可以访问外围类对象的全部状态。
在java中,static内部类没有这种附加指针,这样的内部类与C++中的嵌套类很相似。
使用内部类访问对象状态
内部类的语法比较复杂。鉴于此情况,我们选择一个简单但不太实用的例子说明内部类的使用方式
下面将进一步分析TimerTest示例,并抽象出一个TalkingClock类,构造一个语音时钟需要提供两个参数:发布通告的事件和开关铃声的标志。
package 第3章;import java.awt.*;import java.awt.event.*;import java.util.*;import javax.swing.*;import javax.swing.Timer;/** * * @author cmx */public class Timer_test{ public static void main (String[] args) { Outer clock=new Outer(1000,true); clock.Beep(); }}class Outer{ private int interval; private boolean beep; public Outer(int interval ,boolean beep) { this.interval=interval; this.beep=beep; } public void Beep() { ActionListener ok=new well(); Timer t=new Timer(interval,ok); t.start(); } /** * 以下为内部类 InnerClass */ public class well implements ActionListener { public void actionPerformed(ActionEvent e) { System.out.println("this is the "+new Date()); if(beep) Toolkit.getDefaultToolkit().beep(); } }}
内部类的特殊语法规则
我们已经讲述了内部类有一个外围类的引用outer。事实上,使用外围类引用的正规语法还要复杂一些。表达式
OuterClass.this
表示外围类引用。例如,可以像下面这样编写TimerPrinter内部类的actionPerformed方法
原方法:
public class well implements ActionListener { public void actionPerformed(ActionEvent e) { System.out.println("this is the "+new Date()); if(beep) Toolkit.getDefaultToolkit().beep(); } }
完整语法:
public void actionPerformed(ActionEvent event){ ... if(Outer.this.beep) Toolkit.getDefaultToolkit().beep();}
代替:
if(beep) Toolkit.getDefaultToolkit().beep();
反过来,可以采用下列语法格式更加明确的编写内部类对象的构造器
原默认构造器:
//调用函数中,外部类的引用为:Outer O=new Outer(...);public well(Outer c){ O=c; //?}
//新内部对象构造器:public well(Outer c){ O.new well(construction parameter) //?}
例如:
ActionListener ok=this.new well();
在这里,最新构造的well对象的外围类引用被设置为创建内部类对象的方法中的this引用。这是一最常见的情况。通常,this限定词是多余的。不过,可以通过显式的命名将外围类引用设置为其他的对象。例如:如果well是一个公有的内部类,对于任意的语音时钟都可以构造一个well:
//原引用方式:public class Timer_test{ public static void main (String[] args) { Outer clock=new Outer(1000,true); clock.Beep(); }}+class Outer{ private int interval; private boolean beep; public Outer(int interval ,boolean beep) { this.interval=interval; this.beep=beep; } public void Beep() { ActionListener ok=new well(); // ActionListener ok=this.new well(); Timer t=new Timer(interval,ok); t.start(); }
新的引用方式
Outer j=new Outer(1000,true); //外围类引用(总调用)Outer.well a=j.new well();
也就是:
public class Timer_test{ public static void main (String[] args) { Outer clock=new Outer(1000,true); clock.Beep(); /* Outer j=new Outer(1000,true); //外围类引用(总调用) Outer.well a=j.new well(); */ }}
需要注意:在外围类的作用域外,可以这样引用内部类:
OuterClass.InnerClass例如:Outer.wellOuter j=new Outer(1000,true); //外围类引用(总调用) Outer.well a=j.new well();
注意:内部类中声明的所有静态域都必须是final。原因很简单。我们希望一个静态域只有一个实例,不过对于每一个外部对象,会分别有一个单独的内部类实例。如果这个域不是final,他可能就不是唯一的。
如果不是final就出出现:
Cannot refer to a non-final variable mylis inside an inner class defined in a different method
内部类不能有
- 【Java】【内部类】Java 内部类简介
- [Java] Java 内部类
- Java 内部类(成员内部类、局部内部类、静态内部类和匿名内部类)
- Java内部类(成员内部类、静态内部类、局部内部类、匿名内部类)小结
- Java内部类(成员内部类、静态内部类、局部内部类、匿名内部类)小结
- Java内部类(成员内部类、局部内部类、静态内部类、匿名内部类)
- Java内部类(成员内部类、静态内部类、局部内部类、匿名内部类)小结
- Java内部类(成员内部类、静态内部类、局部内部类、匿名内部类)小结
- Java内部类(成员内部类、静态内部类、局部内部类、匿名内部类)小结
- java的内部类、匿名内部类、局部内部类
- java内部类之成员内部类、静态内部类
- java 成员内部类 局部内部类,匿名内部类
- Java 静态内部类/内部类
- java内部类、静态内部类 小结
- Java内部类,静态内部类
- JAVA 内部类与静态内部类
- java内部类--局部内部类
- Java 内部类以及匿名内部类
- udhcp源码详解
- 【Java学习笔记】接收命令行参数输出指定个数的斐波那契数列
- 学习-基于遗传算法的多目标优化算法
- 构造函数的细节
- Multi-Programming-17 Semaphore & CountDownLatch信号量和计数栓之间的关系
- java 内部类
- 硕士研究僧长成记
- 10_ID生成策略_xml_配置
- mongoDB备份与恢复
- 学习Linux-4.12内核网路协议栈(2.1)——接口层加快传输速率的特性
- 二叉树的简单实现
- Maven无网络条件下搭建项目的方法
- pybitcointools源码分析之RFC6979
- 学习Linux-4.12内核网路协议栈(2.2)——接口层数据包的接收(上半部)