Java_OOP-高级篇6(内部类)

内部类

基本介绍

一个类的内部嵌套了另一个类结构,被嵌套的类称之为内部类

最大特点:可以直接访问私有属性;可体现类之间的包含关系

语法

class Outer{//外部类
    class Inner{//内部类
        
    }
}
class Other{//外部其他类
    
}

种类

​ 定义在外部类的局部上(如方法体内):

  1. 局部内部类
  2. 匿名内部类(无类名,重点🚩🚩🚩)

​ 定义在外部类的成员上(如属性位置):

  1. 成员内部类(无static修饰)
  2. 静态内部类(有static修饰)

局部内部类

语法
class Outer{
    private void met(){//在方法体内
        class Inner{}//局部内部类
    }
}
细节与注意
  • 一般定义在局部位置,通常在方法体(有类名)

  • 可以直接访问外部类所有成员,包括私有成员

  • 不能加修饰符,但是可以使用final修饰

  • 作用域:仅仅在定义该内部类的方法里或者代码块中

  • 访问:

    1. 局部内部类---》访问---》外部类成员【直接访问】;
    2. 外部类---》访问---》内部类成员【在作用域内创建对象,再访问】
    3. 外部其他类-----不可访问------局部内部类【地位与局部变量一样】
  • 外部类与局部内部类有重名成员时:访问遵循就近原则;若想访问外部类同名成员。可使用:外部类名.this.成员(属性、方法)

package com.java_learn.oop_advanced.inner_;

public class LocalInner {
    public static void main(String[] args) {
        /**
         * 局部内部类使用
         */
        LocalOuter localOuter = new LocalOuter();
        localOuter.m2();
    }
}
class LocalOuter{
    private int o_n=10;
    private void m1(){
        System.out.println("这里是外部类LocalOuter的m1方法");
    }
    public void m2(){
        System.out.println("这里是外部类LocalOuter的m2方法");
        class LocalInner{//局部内部类不能使用修饰符,可以使用final
            private int i_n=20;
            private int o_n=100;//与外部类重名属性,调用遵循就近原则;
            // 若想访问外部类的o_n,可使用 外部类名.this.属性名 访问
            private void i_m(){
                System.out.println("这里是内部类LocalInner的i_m方法");
            }
            private void  showi_n(){
                System.out.println("外部类属性o_n:"+o_n);//🚩可以直接访问外部类
                System.out.println("外部类属性o_n:"+LocalOuter.this.o_n);//🚩使用外部类名.this.属性名访问同名属性
            }
        }
        LocalInner localInner = new LocalInner();//外部类访问内部类成员,需要实例化
        localInner.showi_n();
    }
}

匿名内部类🚩🚩🚩

语法
class Outer{
    private void met(){//在方法体内
        new 类/接口(参数列表){}//匿名内部类
    };//注意有分号
}
细节与注意(🚩重点理解底层实现)
  • 一般定义在局部位置,通常在方法体(没有类名);⚡同时还是一个对象
  • 可以直接访问外部类所有成员,包括私有成员
  • 不能加修饰符
  • 作用域:仅仅在定义该内部类的方法里或者代码块中
  • 外部其他类-----不可访问------局部内部类【地位与局部变量一样】
  • 外部类与局部内部类有重名成员时:访问遵循就近原则;若想访问外部类同名成员。可使用:外部类名.this.成员(属性、方法)
  • 底层:以外部类名$1 来命名匿名内部类
  • jdk创建了匿名类后,立即new了一个外部类名$1实例,赋给引用变量
  • 匿名内部类执行一次赋给引用变量后不可再使用,该类实例的对象可用
  • 运行类型:匿名内部类的底层分配类名:外部类$匿名类序号
package com.java_learn.oop_advanced.inner_;
public class AnonymousInner {
    public static void main(String[] args) {
        /**
         * 匿名内部类使用
         */
        A_Outer a_outer = new A_Outer();
        a_outer.A_met();//匿名内部类实现
    }
}
class A_Outer {
    //🚩需求:有多个类实现IA接口,⚡但是每个类只使用一次

    //传统方法:创建多个类,实现show方法;这里创建了类Cat
    //问题:代码可用性不高,繁琐
    public void t_met() {
        Cat cat = new Cat();
        cat.show();
    }

    //匿名内部类实现:简化开发
    public void A_met() {
        /*⚡⚡⚡
        cat 的编译类型:IA
        cat 的运行类型:匿名内部类
        *****解析运行类型******
        匿名内部类底层:
        class XXXX implements IA{//此XXXX即为系统分配类名,只有调用getClass方法可看;即为》》(外部类$1)
        public void show() {
                System.out.println("匿名内部类实现了show方法");
            }
        }
         */
        //基于接口 的匿名内部类
        IA cat = new IA() {
            public void show() {
                System.out.println("匿名内部类实现了show方法");
            }
        };
        cat.show();
        System.out.println("匿名内部类的类名:"+cat.getClass());

        //基于类 的匿名内部类
        /*⚡⚡⚡
        底层实现:
        class xxx extends  Bud{};  xxx为系统分配类名---》A_Outer$2
        运行类型:A_Outer$2
         */
        Bud bud = new Bud(){
			//因为底层实现继承,这里可不重写,继承父类b_met方法
        };
        bud.b_met();
        System.out.println("基于类实现的匿名内部类名:"+bud.getClass());
    }
}
class Bud{
    public void b_met(){
        System.out.println("这是Bud类的b_met方法");
    }
}
interface IA {
    void show();
}
//传统实现方法创建Cat
class Cat implements IA {
    @Override
    public void show() {
        System.out.println("这里小猫实现了show方法");
    }
}
  • 匿名内部类做参数⚡⚡⚡
package com.java_learn.oop_advanced.inner_;

public class Exercise {
    public static void main(String[] args) {
        met(
                new Nu() {
                    @Override
                    public void show() {
                        System.out.println("这里通过匿名内部类作参数");
                    }
                }
        );
    }
    public static void met(Nu n){
        n.show();
    }
}
interface Nu{
   default void show(){
       System.out.println("这里是接口的方法");
   };
}
实践
package com.java_learn.oop_advanced.inner_;

public class Exercise01 {
    public static void main(String[] args) {
        Cellphone.alarmclock(
                new Bell() {
                    @Override
                    public void ring() {
                        System.out.println("起床了");
                    }
                }
        );
    }
}
interface Bell{
    void ring();
}
class Cellphone{
    public static void alarmclock( Bell b){
        b.ring();
    }
}

成员内部类

语法
class Outer{
	private int a=12;
    class Inner{
  //与成员地位一致
    }
}
细节与注意
  • 可添加任意修饰符(地位和属性一样)
  • 内部类---》访问---》外部类成员【直接访问】
  • 外部类----》访问---》成员内部类【在外部类方法创建对象,再调用】
  • 外部其他类---》访问---》成员内部类
package com.java_learn.oop_advanced.inner_;

public class MemberInner {
    public static void main(String[] args) {
        /**
         * 成员内部类
         */
        M_Outer m_outer = new M_Outer();
        m_outer.show();
        //外部其他类访问成员内部类
        //方法1
        M_Outer.M_Inner m_inner = m_outer.new M_Inner();
        m_inner.M_met();
//        方法2:创建一个方法返回成员内部类的对象
        m_outer.innerInstance().M_met();

    }
}
class M_Outer{
    private int age=12;
    class M_Inner{
        private  int a=21;
        public void M_met(){
            System.out.println("这里是成员内部类的方法");
        }
    }
    public  void show(){//在外部类方法中实例化再调用
        M_Inner m_inner = new M_Inner();
        m_inner.M_met();
    }
    public M_Inner innerInstance(){
        return new M_Inner();
    }
}

静态内部类

语法
class Outer{
    private int a=12;
    static class Inner{
        
    }
}
细节与注意
  • 可以访问外部类所有静态成员,包括私有;但是不能直接访问非静态成员
  • 可以有任意修饰符
  • 外部类与局部内部类有重名成员时:访问遵循就近原则;若想访问外部类同名成员。可使用:外部类名.成员(属性、方法)(注意没有this。因为此时为静态内部类)
package com.java_learn.oop_advanced.inner_;

public class StaticInner {
    public static void main(String[] args) {
        S_Outer s_outer = new S_Outer();
        //方法1
        s_outer.innerInstance().S_met();
        //方法2
        S_Outer.S_Inner s_inner = new S_Outer.S_Inner();
        s_inner.S_met();

    }
}
class S_Outer{
    private static int a=10;
    private int b=20;
    static class S_Inner{
        private int a=30;
        public void S_met(){
            System.out.println("这是静态内部类的方法");
        }
    }
    public S_Inner innerInstance(){
        return new S_Inner();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值