Java内部类

112 阅读2分钟

类的五大成员

属性、方法、构造器、代码块、内部类
底层源码包含大量的内部类

基本语法

class Outer {
    class Inner {
    
    }
}

即在类的内部定义一个类

内部类分类

在外部类的局部位置上

局部内部类(有类名)

比如在方法中定义

public class Main {
    Outer outer02 = new Outer;
    outer02.ma();
}

class Outer {
    private int n1 = 100;
    private void m2(){} 

    public void m1() {//方法

        class Inner{//局部内部类,有类名
        //1.可以访问外部类的所有成员、包含私有
        //2.不能用除final以外的修饰符(不能被继承)
        //3.作用域仅在方法或代码块内
            public void f1() {
                //4.局部内部类可以直接访问外部类的成员
                //7.若外部类成员与内部类成员重名时,默认就近,若想访问外部类成员
                //  使用“外部类名.this.成员”访问
                private int n1 = 7;
                System.out.println(n1);//这时由于就近会输出7
                m2();
                //Outer.this其实就是一个对象,调用m1方法的对象,这里就是outer02
                System.out.println(Outer.this.n1);//输出100

            }
        }
        //4.外部类可以创建内部类的实例,调用方法即可
        Inner inner1 = new Inner();
        inner1.f1();//可以用于反射后调用方法
    }
}
  1. 定义在方法或代码块中
  2. 作用域在方法体或代码块中
  3. 本质仍然是个类

匿名内部类(没有类名,重点!!!)

  1. 本质还是类
  2. 它是一个内部类
  3. 它是匿名的
  4. 该类没有名字(系统帮你取名,系统分配)
  5. 同时它还是一个对象
  6. 在局部位置上
基本语法
new 类或接口(参数列表) {
    类体
};
基于接口
  • 实例
public class AnonymousInnerClass {
    public static void main(String[] args) {
        outer o1 = new outer();
        o1.m1();
    }
}

class outer {
    private int n1 = 10;
    public void m1() {
        //基于接口的匿名内部类
        /**
         * 1.需求使用接口IA,并创建对象
         *   传统方法:创建一个类继承接口,创建类的实例对象并使用该方法
         *   有一种情况,这个方法只使用一次,去定义类很麻烦,此时使用匿名内部类简化开发
         */
        //tiger编译类型:IA
        //tiger的运行类型:匿名内部类
        /**
         * 底层
         * class xxxx implements IA {
            *  @Override
                public void cry() {
                    System.out.println("growling...");
                }
         * }
         * xxxx=外部类名$1,可用tiger.getClass()查看,看到$就知道是匿名内部类
         */
        //以下这个new就是创建xxxx$x实例,并把地址(堆里的对象)返回给tiger
        //匿名内部类只能用一次,但是tiger这个对象可以反复使用
        IA tiger = new IA() {
            @Override
            public void cry() {
                System.out.println("growling...");
            }
        };
        tiger.cry();
        tiger.cry();
        tiger.cry();
    }
}

interface IA {
    public void cry();
}
基于类
public class AnonymousInnerClass {
    public static void main(String[] args) {
        outer o1 = new outer();
        o1.m1();
    }
}

class outer {
    private int n1 = 10;
    public void m1() {
        Father father = new Father("jack") {
            //编译类型:Father
            //运行类型:outer$2(不带大括号就是Father)
            /**
             * class Outer$2 extends Father {
             * }
             */
            @Override
            public void test() {
            //动态绑定
                System.out.println("重写");
            }
        };
    }
}

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

也可以

new Father("jack") {    
    @Override
    public void test() {
        System.out.println("重写");
    }
}.test();

还可以super.方法名()这样会调用父类方法

定义在外部类成员位置上

成员内部类(没有static修饰)

外部类对象名.内部类名 对象 = 外部类对象名.new 内部类名();或者在外部类编写相应的内部类访问方法

静态内部类(使用static修饰)

只能直接访问外部类的静态成员