详解 内部类 —— 内部类 与 匿名内部类

在本人之前的篇博文《详解 抽象类》中,讲到的对抽象类的使用手段是:
1.继承抽象类,并且实现其抽象方法,产生新类(子类)
2.实例化这个子类,完成抽象方法的实现。
但是,对抽象类的使用手法并不是唯一的,还有一种更直接、更犀利的实现手段,但这种手段是建立在内部类的知识基础上的,所以,在讲这种手段前,本人有必要先讲解一下 内部类 这个知识点。
并且本人谈到:这篇博文中所要讲解的知识,将会在本篇博文中提现到作用。
那么,废话不多说,现在就开始本篇博文主题的讲解吧!



内部类:

定义: 把类定义在其他类的内部,这个类就被称为内部类。

内部类 和 外部类 之间的访问特点

访问特点

  • 内部类可以直接访问外部类的成员,包括私有。
  • 外部类要访问内部类的成员,必须创建对象。

而我们可以根据内部类的位置,对内部类分为如下两类:

按照内部类位置分类

  • 成员位置:
    成员位置定义的类,被称为成员内部类
  • 局部位置:
    局部位置定义的类,被称为局部内部类

而对于这两种内部类,他们的修饰符也略有差别:
首先是 成员内部类

成员内部类的修饰符:

  • private 为了保证数据的安全性
  • static 为了方便访问数据

注意事项:

  1. 静态内部类访问的外部类数据必须用静态修饰
  2. 成员方法可以是静态的也可以是非静态

接下来是局部内部类

final修饰

  • 因为局部变量随着方法的调用完毕而消失,这个时候,局部对象并没有立马从堆内存中消失,还要使用那个变量
    为了让数据还能继续被使用,就用fianl修饰,这样,在堆内存里面存储的其实是一个常量值

注意事项:
JDK1.8之后,final会默认加上,不需要手动去加

那么,我们如何在 外部类中 直接访问内部类的成员呢?

外部类访问内部类成员的手段:
格式:

  1. 一般格式:
    外部类名.内部类名 对象名 = 外部类对象.内部类对象;
  2. 成员内部类静态修饰后:
    外部类名.内部类名 对象名 = 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地精髓!

猜你喜欢

转载自www.cnblogs.com/codderYouzg/p/12418349.html