Java复习知识点十三:四种内部类:局部内部类、匿名内部类、成员内部类、静态内部类

1、四种内部类

一个类的内部又完整的嵌套另一个类结构。被嵌套的类称为内部类(inner class)

内类的分类:

定义在外部类局部位置上(比如方法内):

  1. 局部内部类(有类名)
  2. 匿名内部类(没有类名,重点!!!)

定义在外部类的成员位置上:

  1. 成员内部类(没用static修饰)
  2. 静态内部类(使用static修饰)

1.1 局部内部类

局部内部类是定义在外部类的局部位置中,比如方法中,并且有类名

外部类调用局部内部类:

只能使用 外部类对象 调用 局部内部类所处方法,并且在方法中创建局部内部类的实例

public class OuterMain{
    public static void main(String[] args) {
        Outer outer = new Outer("李四");
        //局部内部类所处的成员方法
        outer.m2();
    }
}

class Outer {//外部类

    private String name; //属性

    public Outer(String name){//构造器
        this.name = name;
    }

    public void m1(){
        System.out.println("外部类的成员方法m1()");
    }

    public void m2(){
        class Inner {//局部内部类
            private String name = "张三";
            public void f1(){
                //可直接访问外部类成员
                m1();
                //外部类和内部类的成员重名时,默认遵循就近原则
                //访问外部类成员 使用 外部类名.this.成员名
                System.out.println("内部类的name:"+ name);
                System.out.println("外部类的name:"+ Outer.this.name);
            }
        }
        //只能在方法中创建内部类的对象,然后调用方法
        Inner inner = new Inner();
        inner.f1();
    }

}

类似一个局部变量

  1. 可以直接访问外部类的所有成员,包含私有的
  2. 不能添加访问修饰符,但可以使用final修饰
  3. 作用域:仅仅在定义它的方法或代码块中,因为局部内部类的地位相当于一个局部变量
  4. 局部内部类可以直接访问外部类的成员
  5. 外部其它类不能访问局部内部类(局部内部类的地位相当于一个局部变量)
  6. 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类.this.成员)去访问

1.2 匿名内部类

本质是类,内部类,该类没有名字,同时还是一个对象

基于接口、类、抽象类的匿名内部类:

package inner;

/**
 * @Author 孑然
 */
public class AnonymousInnerClass {
    public static void main(String[] args) {
        //基于接口的匿名内部类
        //底层分配类名:AnonymousInnerClass + $1
        //jdk底层在创建匿名内部类AnonymousInnerClass$1后,立即就创建了
        //AnonymousInnerClass$1的实例,并且把地址返回给 ia
        IA ia = new IA() {
            @Override
            public void cry() {
                System.out.println("老虎叫唤");
            }
        };
        ia.cry();
        System.out.println(ia.getClass());

        //基于类的匿名内部类
        //编译类型 Father
        //运行类型 AnonymousInnerClass$2
        Father father = new Father("王二"){
            @Override
            public void test() {
                System.out.println("匿名内部类重写了test方法");
            }
        };
        father.test();
        //AnonymousInnerClass$2
        System.out.println("father的运行类型:"+father.getClass());

        //基于抽象类的匿名内部类
        //编译类型:Animal
        //运行类型:AnonymousInnerClass$3
        Animal animal = new Animal(){
            @Override
            void test() {
                System.out.println("匿名内部类重写了test方法");
            }
        };
        animal.test();
        System.out.println("animal的运行类型:"+animal.getClass());
    }
}

interface IA {
    void cry();
}
class Father {

    public Father(String name){
    }
    public void test(){

    }
}
abstract class Animal {
    abstract void test();
}

使用细节:

  1. 匿名内部类的地位也相当于外部类的一个局部变量
  2. 成员变量与外部类的成员变量重名时,也是默认遵循就近原则
  3. 若想访问同名的外部成员,可使用(外部类名.this.成员)去访问

1.3 匿名内部类的最佳实践

当做实参直接传递,简洁高效

public class InnerClassExercise01 {

    public static void main(String[] args) {
        //使用匿名内部类传参调用f1();
        f1(new IL() {
            @Override
            public void show() {
                System.out.println("这是一幅名画...");
            }
        });
        //传统方法,1.实现IL ,重写show方法,调用f1传入实现类对象
    }

    public static void f1(IL il){
        il.show();
    }

}

interface IL {
    void show();
}

1.4 成员内部类

定义在外部类的成员位置:

package inner;

/**
 * @Author 孑然
 */
public class OuterMain02 {
    public static void main(String[] args) {
        //外部类使用成员内部类的三种方式
        Outer02 outer02 = new Outer02();
        
        //1.相当于把new Inner02()看做outer02的一个成员
        Outer02.Inner02 inner02 = outer02.new Inner02();

        //2.在外部类中编写一个返回成员内部类实例的方法
        Outer02.Inner02 inner02_1 = outer02.getInner02();

        //3.第3 种写法
        Outer02.Inner02 inner02_2 = new Outer02().new Inner02();
        
    }
}
class Outer02 {//外部类
    private int n1 = 10;
    public String name = "张三";

    class Inner02 {//成员内部类
        public void say(){
            //可以直接访问外部类的所有成员,包含私有的
            System.out.println("n1="+n1+",name="+name);
        }
    }
    public Inner02 getInner02(){
        return new Inner02();
    }
}

外部类调用成员内部类的三种方式:

//外部类使用成员内部类的三种方式
        Outer02 outer02 = new Outer02();

        //1.相当于把new Inner02()看做outer02的一个成员
        Outer02.Inner02 inner02 = outer02.new Inner02();

        //2.在外部类中编写一个返回成员内部类实例的方法
        Outer02.Inner02 inner02_1 = outer02.getInner02();

        //3.第3 种写法
        Outer02.Inner02 inner02_2 = new Outer02().new Inner02();

若想访问同名的外部成员,同样使用(外部类名.this.成员)去访问

1.5 静态内部类

带有static修饰符的成员内部类,可以将其看做一个静态的成员变量

内部访问外部:

  1. 可以访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员

外部访问内部:

public class OuterMain03 {
    public static void main(String[] args) {
        //外部其他类访问内部类
        Outer03.Inner03 inner03 = new Outer03.Inner03();
    }
}
class Outer03 {
    public static class Inner03{
        void say(){
            System.out.println("内部类的say方法");
        }
    }
    //外部类访问内部类通过调用f1()方法
    public void f1(){
        Inner03 inner03 = new Inner03();
        inner03.say();
    }
}

若想访问同名的外部成员,使用(外部类名.成员)即可

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值