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


    在本人之前的篇博文《详解 抽象类》中,讲到的对抽象类的使用手段是:
    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地精髓!

  • 相关阅读:
    【Java】【IDE】【Jetbrain Idea】Intellij IDEA 快捷键整理
    【Linux】【Services】【KVM】virsh命令详解
    【Linux】【Services】【KVM】安装与简单配置
    【Linux】【Services】【Docker】Docker File
    【Linux】【Services】【Docker】网络
    【Linux】【Services】【Docker】应用
    【Linux】【Services】【Docker】基础理论
    【Python】【Module】json and pickle
    【Python】【Module】hashlib
    Highcharts 对数组的要求
  • 原文地址:https://www.cnblogs.com/codderYouzg/p/12418349.html
Copyright © 2020-2023  润新知