目录
内部类:
匿名内部类:
在本人之前的篇博文《详解 抽象类》中, 讲到的对抽象类的使用手段是:
1. 继承抽象类, 并且实现其抽象方法, 产生新类 (子类)
2. 实例化这个子类, 完成抽象方法的实现.
但是, 对抽象类的使用手法并不是唯一的, 还有一种更直接, 更犀利的实现手段, 但这种手段是建立在内部类的知识基础上的, 所以, 在讲这种手段前, 本人有必要先讲解一下 内部类 这个知识点.
并且本人谈到: 这篇博文中所要讲解的知识, 将会在本篇博文中提现到作用.
那么, 废话不多说, 现在就开始本篇博文主题的讲解吧!
内部类:
定义: 把类定义在其他类的内部, 这个类就被称为内部类.
内部类 和 外部类 之间的访问特点:
访问特点:
内部类可以直接访问外部类的成员, 包括私有.
外部类要访问内部类的成员, 必须创建对象.
而我们可以根据内部类的位置, 对内部类分为如下两类:
按照内部类位置分类
成员位置:
在成员位置定义的类, 被称为成员内部类
局部位置:
在局部位置定义的类, 被称为局部内部类
而对于这两种内部类, 他们的修饰符也略有差别:
首先是 成员内部类:
成员内部类的修饰符:
private 为了保证数据的安全性
static 为了方便访问数据
注意事项:
静态内部类访问的外部类数据必须用静态修饰
成员方法可以是静态的也可以是非静态的
接下来是局部内部类:
final 修饰:
因为局部变量会随着方法的调用完毕而消失, 这个时候, 局部对象并没有立马从堆内存中消失, 还要使用那个变量.
为了让数据还能继续被使用, 就用 fianl 修饰, 这样, 在堆内存里面存储的其实是一个常量值.
注意事项:
JDK1.8 之后, final 会默认加上, 不需要手动去加
那么, 我们如何在 外部类中 直接访问内部类的成员呢?
外部类访问内部类成员的手段:
格式:
一般格式:
外部类名. 内部类名 对象名 = 外部类对象. 内部类对象;
成员内部类 被 静态修饰后:
外部类名. 内部类名 对象名 = new 外部类名. 内部类名 ();
那么, 本人还是通过一段代码来讲解内部类的使用方法:
OuterClass 类:
- package com.mec.about_inner.core;
- public class OuterClass {
- private int privateMember;
- protected int protectedMember;
- public int publicMember;
- public OuterClass() {
- // 这里定义三种不同的权限修饰符的成员
- privateMember = 1;
- protectedMember = 2;
- publicMember = 3;
- }
- // 这里定义三种不同的权限修饰符的方法
- private void privateFun() {
- System.out.println("privateMember:" + privateMember);
- }
- protected void protectedFun() {
- privateFun();
- System.out.println("protectedMember:" + protectedMember);
- }
- public void publicFun() {
- privateFun();
- System.out.println("publicMember:" + publicMember);
- }
- public class InnerClass {
- private int innerMember;
- public InnerClass() {
- innerMember = 4;
- }
- private void InnerFun() {
- privateMember++;
- protectedMember++;
- publicMember++;
- privateFun();
- protectedFun();
- publicFun();
- System.out.println("innerMember:" + innerMember);
- }
- }
- // 外部类可以定义其内部类对象的成员
- private InnerClass innerObject;
- public void fun() {
- // 外部类可以实例化该成员, 并且可根据内部类的对象, 引用内部类的成员和方法
- innerObject = new InnerClass();
- innerObject.InnerFun();
- System.out.println(innerObject.innerMember++);
- }
- }
上面代码的注意点, 本人已经在注释中写清楚了, 所以在这里不再进行详细解释.
在这里本人只提醒一点:
内部类中的任何成员和方法, 都可以被直属外部类调用.
外部类中的任何成员和方法, 都可以被其所包含的内部类调用.
但是, 在这里, 本人要展示下 bin 目录下所生成的 *.class 文件:
可见, 这里额外生成了一个名为 "OuterClass$InnerClass" 的类, 而这个名称, 就表明这个类是在 OuterClass 类中的内部类 InnerClass 类.
那么, 为什么本人在讲解直接使用抽象类的手段前, 要讲解内部类呢?
那是因为, 这种直接使用抽象类的手段, 被称为 "匿名内部类"
匿名内部类:
首先, 本人来解释下, 什么是匿名内部类:
定义: 就是局部内部类的简化写法
匿名内部类也存在着特定的格式:
格式:
new 类名或者接口名 (){
重写方法;
} ;
根据这个格式, 我们大概能够看的出来:
所谓的匿名内部类 是一个继承了该类 或者 实现了该接口 的 子类匿名对象.
本人在这里再提醒一点:
在匿名内部类中出现的 this, 代表的是该匿名内部类 这个对象
现在, 本人来给一个抽象类:
Bird 类:
- package com.mec.about_inner.core;
- public abstract class Bird {
- private String name;
- public Bird(String name) {
- this.name = name;
- }
- public abstract String cry();
- public void print( ) {
- System.out.println("(" + name + ")" + "的叫声:" + cry());
- }
- }
接下来, 本人通过 Test 类, 来展示直接使用抽象类的手段:
Test 类:
- package com.mec.about_inner.core;
- public class Test {
- public static void main(String[] args) {
- // 第一种手段的展示
- Bird lark = new Bird("百灵鸟") {
- @Override
- public String cry() {
- return "百灵既洽, 祚我王国";
- }
- };
- lark.print();
- // 第二种手段的展示
- new Bird("乌鸦") {
- @Override
- public String cry() {
- return "月影笼缁衣, 寒鸦枝上啼";
- }
- }.print();
- // 第三种手段的展示
- new Bird("黄鹂") {
- public Bird fun() {
- System.out.println("这里是第三种调用抽象类的方法");
- return this;
- }
- @Override
- public String cry() {
- return "烟红露绿晓风香, 燕舞莺啼春日长";
- }
- }.fun().print();
- }
- }
这里对上面的代码做一些解释:
这三种手段, 其实是一种手段, 都利用了如下模式:
new 抽象类构造方法 () {
抽象类的所有抽象方法的实现;
}
剩下的操作, 都是建立于这中方式的基础上才产生的, 但是本质是一样的.
下面, 本人再来展示下现在的 bin 目录下的 *.class 文件:
可以看到, 多生成了三个内部类, 但是这三个内部类却没有有意义的名称, 所以, 这三个类被称为 "匿名内部类".
本人在这里做一下说明:
一个 匿名内部类 最好对应 一种 抽象方法的实现, 这样使得我们的工具的功能更加单一化, 在修改时不容易导致其他工具出错.
但是本人在这里想要提醒一句话, 到了这里, Java 的 "工具化" 思想想必是非常突出的了, 所以, 同学们时刻要注意无论 Java 学习到哪种程度,"工具化" 思想都要时刻铭记, 只有这样, 才能真正地掌握 Java 地精髓!
来源: http://www.bubuko.com/infodetail-3447767.html