当前课程知识点:Java程序设计 > 第七章 图形用户界面 > 7.5-内部类 > 内部类
大家好
欢迎回来继续学习
Java语言程序设计
接下来这一节呢
我们来初步了解一下
内部类这种语法机制
在这一节我并不打算
详细深入的去介绍
内部类的语法
因为我不觉得它不属于
我们入门课程所必须掌握的
最重要的内容
但是又要给大家做一点
简单介绍
为什么呢
是因为当我们要响应
这些图形用户界面的组件的
发生的这些交互的时候
我们要用这个事件监听机制
当我们向组件上面
去添加事件监听器
去注册这个响应事件的
代码的时候
其中有一种方法
就是使用匿名的内部类
这是一种非常常用的方法
为了让大家能够理解这些代码
我在这儿将内部类这种语法机制
给大家做一个非常简单的介绍
顾名思义什么是内部类呢
就是写在别的类的
类体内部的那个类
定义在另外一个类
或者是方法体
或者是某一个很小的模块里面的
这个类呢就叫做内部类
内部类可以访问
它的外部类中的所有数据成员
和方法成员
用这样的方式我们可以对逻辑上
相互关联的类进行分组
写在内部的类呢
即使对同一个包中的其他类来说
也是看不见的
是能够隐藏起来的
这样的话呢
我们就可以隐藏一些实现细节
用内部类可以非常方便的
编写事件驱动程序
那内部类怎么声明呢
我们可以给内部类命名
命名了以后
就可以在外部类里边多次使用
如果说你只希望使用一次
那么干脆对这个内部类
也可以不命名
也就是匿名的内部类
我们知道在java中
每一个类在编译之后
都会形成一个独立的class文件
内部类也不例外
如果你为内部类命名了
那它就会按照外部类(02:52英文)
然后内部类这样的名字
给这个class文件命名
如果是一个匿名的内部类
那么就在外部类名之后
给一个编号
表示这个匿名内部类的一个编号
那么它也是占有一个独立的
class文件的
接下来我们就来看一个
简单的内部类的例子
现在我们来看一下
以这个某种包裹类为例
我们知道包裹呢
它就要有包裹内容
还要有你邮寄的目的地
目的地标签
那么这个包裹里面有一个ship
是邮寄方法
邮寄方法就得将有内容的包裹
邮寄到目的地去
那么比如说我们现在看主方法中
我们要做什么呢
我们要构造一个包裹对象
然后把它邮寄到哪儿
邮寄到比如说坦桑尼亚去
那这个时候呢
包裹内容应该用一个类的对象
来表示
邮寄的目的地
我们认为也应该
用一个类的对象来表示
那么这时候有没有必要
写两个独立的类呢
没有必要
为什么
因为这个内容也好
目的地也好
都只在包裹类里面用得上
在其他地方我们任务它没有用
如果是这种情况下的话
我们就可以把这个Contents
和Destination这两个类
干脆写在Parcel1这个类里面就行了
我们看这就是两个内部类
然后这个我们看这个ship方法
ship方法里面
构造了一个Contents对象
构造了一个Destination对象
也就是说我们要邮寄的话
需要有另外两个类的对象来帮忙
起辅助作用
那么我们就把需要的这样的
仅仅在Parcel1这个类中
才用得上的类就定义成内部类
在接下来这个例子中
我们让这个外部类的方法
可以返回一个
指向内部类对象的引用
我们再来看这个例子里面
在这个Parcel2
里面同样也有一个Contents
一个Destination这两个内部类
然后这儿有一个to方法
而这个to方法
它返回一个Destination引用
那么这个Destination呢
是一个内部类的类名
所以我们看到外部类的方法
可以来返回内部类的引用
还有这个Cont方法也是同样
它返回一个Contents引用
它构造一个Contents对象
这个是构造一个Destination对象
然后它们都是返回的是内部引用
然后现在我们来看另外一个方法
ship方法
ship方法呢
它调用Cont
得到了一个Contents引用
调用to
得到了一个Destination引用
然后它去输出一行信息
模拟这个邮寄的过程
那么在主方法中
我们构造了一个Parcel2的对象
然后去调用它的ship方法
接下来我们来 也再测试一下
我们可以调用Cont方法
得到了什么呢
得到了它内部类Contents的引用
那么我们在这儿怎么去使用内部类
我们看到名字应该是
外部类点内部类的类名
应该这样来用
如果我们希望彻彻底底去隐藏
这个内部类
让外界根本不知道
有一个内部类存在
那么我们可以首先
去定义一个接口
或者是一个抽象类
然后让这个内部类呢
去实现接口
去扩展抽象类
这样的话我们向外透露的
或者向外展示的
可以仅仅是指向接口的引用
或者是指向抽象类的引用
但是实际上实现这个接口的
或者是扩展这个抽象类的
是哪个内部类
外面就不得而知了
用这样的办法呢
我们就可以达到隐藏内部的
实现细节的目的
我们使用内部类的
很重要的一个目的
就是想隐藏实现细节
也就是说我们并不希望
外界知道我们还有一个
什么内部类
所以我们可以采用这样的方式
比如说我们定义
一个抽象类Contents
定义一个接口Destination
它们都没有实现
都没有实现
里面都是有抽象方法
接下来我们再来看
在Parcel3里面
定义这个pContents
这个内部类的时候
让它去扩展Contents
这个抽象类
并且去实现了里面的抽象方法
当然除此而外呢
还增加了自己的数据成员
那么定义这个
第二个内部类
pDestination的时候
让它去实现了Destination接口
同样它要实现接口的抽象方法
并且还增加了其他的方法和成员
这样我们再来看
这个外部类的dest方法
它的返回值就可以不必暴露
有什么内部类了
它返回值是一个什么
Destination引用
是一个接口的引用
再看看这个Cont
它返回的是一个Contents引用
是这个抽象类的引用
那么这样外界就根本不知道
这里面还有两个内部类了
因为它返回的
都是在外部定义过的
抽象类和接口的引用
而抽象类和接口
它的实现细节是没有的
只是一个抽象方法的
原型的定义
而这个内部类呢
除了覆盖抽象方法以外
它还有一些其他自己新增的成员
也被隐藏起来
外面看不见了
现在我们将这个测试代码
放在另外一个类里面
就是名词叫test这个类
这就跟刚才不一样了
不是在同一个类中写类方法
而是在另外一个类中
来测试我们刚才的
这个包裹类型
这个时候构造一个Parcel对象的话
Parcel3对象
可以调用它的Cont方法
得到的是什么
得到的虽然我们说
实际上得到的是一个
指向它内部类的对象的引用
但是在外界看起来
只是一个Contents引用
同样这个dest方法
返回的也是一个Destination引用
那这样的话
我们通过这个引用
如果想引用的话
就可以使用Contents里面
曾经声明的这个value
可以使用Destination里面
曾经声明的这个readlabel
当然如果说这个pDestination
它还要增加更多的数据成员和方法
那么这些就都隐藏起来了
就都隐藏起来了
所以从外面看
不知道有一个内部类
就实现了隐藏细节的
这样一个效果
一个内部类不仅可以
定义在类体里面
它还可以定义在更小的范围中
比如说它定义在一个方法的
方法体里面
或者任意一对大括号里面
或者甚至于说是在参数表里面
都有可能
那么这个时候如果这个内部类
它是实现了一个接口
那外界就根本不知道
到底有什么样的一个内部类存在
只看得见这个接口的引用
有的时候我们为了解决
某个问题
确实需要定义一个类
但是又不想让外界知道
这个时候我们就可以
在一个局部的范围内
去定义一个内部类
如果我们并不是在
整个类的范围之内
都需要定义一个什么内部类
来辅助解决问题
而只是在这个类的某个方法中
需要一个其他的类
来辅助解决问题的话呢
我们就可以在方法体中
去定义内部类
我们来看在这个dest方法里面
也就是说我们刚才前面例子中
定义的pDestination
这个内部类
它在别的地方并不起作用
只是dest方法要用它
那干脆我们就把它再缩小范围
就定义到dest方法的方法体里面来
在这里面定义
定义完了以后
就只在这个方法体里面
构造一个pDestination对象
返回用这个对象去做一返回值
那么我们来看这里面呢
返回类型定义的是Destination
那我们实际上返回一个
pDestination
就是初始化的它的引用了
这样的话同样的效果
在主方法中呢
我们也是看不见
有一个内部类的
不仅在主方法中
在这个类的其他方法中
也用不了它
假设我们在邮寄的时候呢
可能有的时候
需要跟踪这个邮件
有的时候不需要跟踪邮件
那好
只有在我们需要跟踪邮件的时候
我们才需要一个内部的跟踪单
如果不需要跟踪的邮件
那这个跟踪单
这个对象就不需要
所以我们来看这个例子
这儿有一个internalTracking
就是在这个邮寄系统中
如果我们内部想要跟踪邮件的话
看它的参数是一个布尔类型的
是个布尔类型的
如果说传来的参数是真是true
那就说明需要跟踪
那这个时候我们就需要一个
TrackingSlip一个跟踪单
好 需要一个跟踪单对象
那么这个跟踪单类型
在别的地方都用不上
没有用
只有在这一种情况下
我们才需要跟踪单
所以就在这儿
这个if分支中
定义这么一个内部类
好 接下来呢因为需要跟踪
我们定义完内部类以后
马上构造一个跟踪单对象
然后去实现跟踪就可以了
那么在其他情况下呢
那我们就不需要跟踪
所以在一个更小的块作用域中
一对大括号中
都可以去定义一个内部类
如果我们定义一个内部类
需要多次使用
那肯定要给它一个名字
如果我们定义一个内部类
就唯一使用一次
就在当前的地方使用一下
那其实它可以连名字都没有
比如说我们如果就是在这个
cont方法的
return语句中
需要构造一个内部类对象
返回的话
那就用这一次
干脆这个内部类名字
也不要给了
我们可以用这样的语法
去定义一个匿名的内部类
看这里面好像是new了
一个Contents
那Contents怎么能实例化呢
它是不能实例化
实际上不是new了一个Contents对象
注意后面还紧跟着一对大括号呢
大括号中还有代码呢
这个语法它表达的是
以Contents为超类
去派生出一个新的类来
一个非抽象的类
那么看看这里面就覆盖了
在Contents中曾经定义的
这个抽象的接口方法
那么这个类它自己就不是抽象的了
所以我们构造这个子类的对象
作为返回值返回
而唯一就用这一次
干脆我们连子类的名字
也不用定义了
那么java里面提供了
像这样的定义
匿名内部类的方法
在这一节呢我们简单的
初步的了解了一下
什么是内部类
也知道了内部类呢
它主要用于什么样的场合
对于这些内容呢
并不需要大家
去了解的非常深入
但是在后面的例题中
当我们需要使用匿名内部类
去作为监听器注册的时候
希望大家能够理解
和看得懂这样的程序
-1.0-导学
--1.0-导学
-1.1-Java与面向对象程序设计简介
--第一章 Java语言基础知识--1.1-Java与面向对象程序设计简介
-1.2-基本数据类型与表达式
-第一章 Java语言基础知识--1.2-基本数据类型与表达式
-1.3-数组
--1.3.1-数组
-第一章 Java语言基础知识--1.3-数组
-1.4-算法的流程控制
--第一章 Java语言基础知识--1.4-算法的流程控制
-1.5-第一章小结
-第一章编程练习题
-课件
--外部链接
-Java环境配置、Eclipse使用、Helloworld程序详解
--使用eclipse建立Java项目、编写和运行Java程序
-Java数据类型
--Java整数类型
--Java浮点类型
--数据类型实战
--数据类型转换
--Java强制类型转换精度损失示例与表达式中的数据类型转换
-Java数组
-Java变量
--Java的变量
-命令行参数
--命令行参数的介绍
-2.0-导学
--2.0-导学
-2.1-面向对象方法的特性
--第二章 类与对象--2.1-面向对象方法的特性
-2.2-1-类声明与对象创建
--第二章 类与对象--2.2-1-类声明与对象创建
-2.2-2-数据成员
--第二章 类与对象--2.2-2-数据成员
-2.2-3-方法成员
--第二章 类与对象--2.2-3-方法成员
-2.2-4-包
--2.2-4-包
--第二章 类与对象--2.2-4-包
-2.2-5-类的访问权限控制
--第二章 类与对象--2.2-5-类的访问权限控制
-2.3-1-对象初始化
--第二章 类与对象--2.3-1-对象初始化
-2.3-2-内存回收
--第二章 类与对象--2.3-2-内存回收
-2.4-枚举类
--2.4-枚举类
--第二章 类与对象--2.4-枚举类
-2.5-应用举例
--2.5-应用举例
-2.6-第2章小结
-第二章编程练习题
-课件
--第二章课件
-3.0-导学
--3.0-导学
-3.1.1-3.1.2-类继承的概念和语法
--第三章 类的重用--3.1.1-3.1.2-类继承的概念和语法
-3.1.3-隐藏和覆盖
--第三章 类的重用--3.1.3-隐藏和覆盖
-3.2-Object 类
--第三章 类的重用--3.2-Object 类
-3.3-终结类与终结方法
--第三章 类的重用--3.3-终结类与终结方法
-3.4-抽象类
--3.4-抽象类
--第三章 类的重用--3.4-抽象类
-3.5-泛型
--3.5-泛型
--第三章 类的重用--3.5-泛型
-3.6-类的组合
--3.6-类的组合
-3.7-小结
--3.7-小结
-第三章编程练习题
-课件
--课件
-4.0-导学
--导学
-4.1-接口
--接口
--第四章 接口与多态--4.1-接口
-4.2.1-4.2.2-类型转换
--类型转换
--第四章 接口与多态--4.2.1-4.2.2-类型转换
-4.2.3-方法的查找
--方法的查找
--第四章 接口与多态--4.2.3-方法的查找
-4.3-多态的概念
--多态的概念
--第四章 接口与多态--4.3-多态的概念
-4.4-多态的应用举例
--多态的应用举例
--第四章 接口与多态--4.4-多态的应用举例
-4.5-构造方法与多态性
--构造方法和多态性
--第四章 接口与多态--4.5-构造方法与多态性
-4.6-本章小结
--本章小结
-第四章编程作业
-课件
--课件
-5.0-导学
--5.0-导学
-5.1.1-5.1.2-异常处理的概念
--第五章 输入输出--5.1.1-5.1.2-异常处理的概念
-5.1.3-5.1.5-异常的处理
--第五章 输入输出--5.1.3-5.1.5-异常的处理
-5.2-输入输出流的概念
--输入输出流的概念
--第五章 输入输出--5.2-输入输出流的概念
-5.3.1-写文本文件
--写文本文件
--第五章 输入输出--5.3.1-写文本文件
-5.3.2-读文本文件
--读文本文件
--第五章 输入输出--5.3.2-读文本文件
-5.3.3-写二进制文件
--写二进制文件
--第五章 输入输出--5.3.3-写二进制文件
-5.3.4-读二进制文件
--读二进制文件
-5.3.5-File类
--File类
-5.3.6-处理压缩文件
--处理压缩文件
-5.3.7-对象序列化
--对象序列化
-5.3.8-随机文件读写
--随机文件读写
-5.4-本章小结
--本章小结
-课件
--课件
-6.0-导学
--导学
-6.1-Java集合框架介绍
--第六章 对象群体的组织--6.1-Java集合框架介绍
-6.2-主要接口及常用的实现类
--第六章 对象群体的组织--6.2-主要接口及常用的实现类
-6.3-常用算法
--常用算法
-6.4-数组实用方法
-6.5-基于动态数组的类型(Vector, ArrayList)
--基于动态数组的类型(Vector, ArrayList)
-6.6-遍历Collection
-6.7-Map接口及其实现
-6.8-第6章小结
--第6章小结
-课件
--课件
-7.0-导学
--导学
-7.1-绘图
--绘图
-7.2-Swing基础
--Swing基础
-7.3-Swing的层次
--Swing的层次
-7.4-布局管理
--布局管理
-7.5-内部类
--内部类
-7.6-事件处理的基本概念
-7.7-事件派发机制
--事件派发机制
-7.8-顶层容器
--7.8-顶层容器
-7.9-中间层容器(一)
-7.10-中间层容器(二)
-7.11-原子组件(一)
-7.12-原子组件(二)
-7.13-原子组件(三)
-7.14-其它Swing特性
-7.15-第7章小结
-课件
--课件