【Java】InnerClass 内部类

Java 允许一个类的定义位于另一个类的内部,前者为内部类,后者称为外部类

InnerClass一般定义它的类或语句块之中外部类引用时必须给出完整的名称

 

成员内部类  &  局部内部类

- 静态成员 内部类

- 非静态成员 内部类

- 匿名内部类

 

静态内部类  成员内部类  局部内部类

// 相对于内部类而言,这是一个外部类
public class OuterClass {
    public int a;
    int b;
    protected int c;
    private int d;

    static int e;
    
    public void memberMethod(){
        System.out.println("外部类的成员方法!");

        // 成员内部类可以创建实例
        InnerClass innerClass = new InnerClass();
        // 静态内部类可以创建实例
        StaticInnerClass staticInnerClass = new StaticInnerClass();
    }

    public static void staticMethod(){
        System.out.println("外部类的静态方法!");
    }

    // 成员内部类和静态内部类 都可以abstract抽象 或者final,都可以被4种权限访问修饰

    // 成员内部类 不允许任何静态存在
    class InnerClass{
        // 成员内部类可以修饰所有访问权限
        public int a;
        int b;
        protected int c;
        private int d;

        // 成员内部类不能写静态方法
        // static void staticMethod(){}

        // 成员内部类可以声明成员方法
        void memberMethod(){
            // 成员内部类可以调用外部类的成员方法
            OuterClass.this.memberMethod();

            // 成员内部类外部类的静态方法也能被调用
            OuterClass.staticMethod();
        }

        // 成员内部类可以构造器
        InnerClass(){}

        // 各个字段的访问
        public void checkField(int a){
            // 形参的a
            a = 50;
            // 本成员内部类的字段a
            this.a = 100;
            // 外部类的字段a
            OuterClass.this.a = 150;
        }
    }

    // 静态内部类
    static class StaticInnerClass{
        // 静态内部类可以修饰所有访问权限
        public int a;
        int b;
        protected int c;
        private int d;

        // 静态内部类可以声明成员方法
        void memberMethod(){
            // 可以调用外部类的静态方法
            OuterClass.staticMethod();

            // 外部类的成员方法不行
            // OuterClass.this.memberMethod();
        }

        // 静态内部类可以声明静态方法
        static void staticMethod(){
            // 可以调用外部类的静态方法
            OuterClass.staticMethod();

            // 外部类的成员方法不行
            // OuterClass.this.memberMethod();
        }

        public void fieldCheck(int a){
            // 形参字段
            a = 100;

            // 静态内部类的字段
            this.a = 150;

            // 外部类字段 只能访问静态方法和静态字段
            OuterClass.e = 300;
        }

        // 静态内部类也可以构造器
        StaticInnerClass(){}
    }

    public void classMethod(){
        // 局部内部类 没有权限访问修饰,只做用在这个方法之内 ,可以设置final修饰局部内部类

        // 被内部类所访问的局部变量必须是Final的
        // x的作用域之存活于这个方法中
        // 当方法调用结束,方法出栈,x变量即被销毁掉
        final int x = 123;
        
        // 局部内部类
        class LocalInnerClass{

            // 但是局部内部类的实例依然才在,依然保持这个x变量的引用指向
            // 如果在局部方法被销毁后调用这个方法,就无法再访问这个x变量,这就是BUG问题
            // 但是在JDK8已经默认隐式的表示这个x变量是final修饰的,x必须是一个常量的存在
            // 即表示如果x被销毁,但其值不发生变化,依然是可以被访问赋予的
            
            // 这个原因在于 局部内部类的实例的作用域大于了这个变量的作用域
            public int returnX(){
                // x += 100; x变量不能被修改
                return x;
            }
        }
    }
    
    // 局部内部类的用法,可以用于返回一个实现某接口的实例出来
    public Comparable getComparable(){
        class LocalInnerClass implements Comparable{
            // 局部内部类重写接口方法
            @Override
            public int compareTo(Object o) {
                return 0;
            }
        }
        // 返回给外部调用
        return new LocalInnerClass();
    }
}
三个内部类

 

静态内部类 和 成员内部类在外部的实例创建与访问

public class ClassTest {
    public static void main(String[] args) {
        //  实例化静态内部类
        OuterClass.StaticInnerClass staticInnerClass = new OuterClass.StaticInnerClass();
        //  静态内部类的成员方法
        staticInnerClass.memberMethod();
        //  静态内部类的静态方法
        OuterClass.StaticInnerClass.staticMethod();

        //  实例化成员内部类,必须要有外部类的实例才可以
        OuterClass outerClass = new OuterClass(); //先创建外部实例
        OuterClass.InnerClass innerClass = outerClass.new InnerClass(); //再通过外部实例调用内部初始化
        //  也可以直接匿名外部类对象,调用内部类初始化
        OuterClass.InnerClass innerClass2 = new OuterClass().new InnerClass();

        // 成员内部类调用成员方法
        innerClass.memberMethod();
    }
}
实例化与访问

 

匿名内部类

public class ClassTest {
    public static void main(String[] args) {
        
        AnonymousInnerClass anonymousInnerClass = new AnonymousInnerClass() {
            // 这就是匿名内部类的类体,匿名,顾名思义,没有类的名字
            
            // 重写接口的方法
            @Override
            public void aicMethod() {
                System.out.println("这就是匿名内部类");    
            }
            
            // 匿名内部类只能声明这一次,不能像显示的类一样保存下来
            // 用于创建去实现一个接口或者继承一个抽象类,或者继承普通类也可以
            // 适用于实现只有一个方法的接口,例如多线程的Runnable
            
            // 注意线程还有一个Callable可以使用
        };
    }
}

// 声明一个接口和一个抽象方法
interface AnonymousInnerClass{
    void aicMethod();
}
匿名内部类

 

posted @ 2020-04-18 11:43  emdzz  阅读(141)  评论(0编辑  收藏  举报