1.  内部类结束

  内部类具有封装型,隐藏程序细节。主要有非静态内部类,静态内部类,匿名内部类几种。

 

2. 非静态内部类

  可用把内部类当作外部类的成员变量/方法来使用,需要依赖外部类对象来使用

public class OutClass {
    private String outStr;

    public void display(){
        System.out.println(outStr);
    }

    //内部类
    public class InnerClass{
        private String innerStr;

        public InnerClass() {
            innerStr = "innner class";
        }

        public void display(){
            System.out.println("Inner class");
            System.out.println(innerStr);
        }
    }

    public static void main(String[] args) {
        OutClass outClass = new OutClass();
        outClass.display();

        OutClass.InnerClass innerClass = outClass.new InnerClass();  //创建内部类需要外部类对象调用
        innerClass.display();
    }
}

 

  非静态内部类还可以定义在方法内

public class OutClass02 {
    private String outStr;

    public void display(){
        class InnerClass{
            private String innerStr;

            public InnerClass() {
                innerStr = "innner class";
            }

            public void display(){
                System.out.println("Inner class");
                System.out.println(innerStr);
            }
        }
        InnerClass innerClass = new InnerClass();  //可以直接创建内部类
        innerClass.display();
    }

    public static void main(String[] args) {
        OutClass02 outClass02 = new OutClass02();
        outClass02.display();
    }
}

 

2. 静态内部类

  静态内部类使用不需要依赖外部对象

public class OutClass03 {
    private String outStr;

    public void display(){
        System.out.println(outStr);
    }

    public static class InnerClass03{
        private String innerStr;

        public InnerClass03() {
            innerStr = "innner class";
        }

        public void display03(){
            System.out.println("Inner class");
            System.out.println(innerStr);
        }
    }

    public static void main(String[] args) {
        OutClass03 outClass03 = new OutClass03();
        outClass03.display();

        InnerClass03 innerClass03 = new InnerClass03();  //创建内部类不需要外部类对象调用
        innerClass03.display03();

    }
}

 

3. 匿名内部类

  可用直接实现接口创建对象,还可以直接"new 接口名“,重写接口中方法

public interface InnerInterface {
    void inner();
}
public class InnerInterfaceImpl implements InnerInterface {
    @Override
    public void inner() {
        System.out.println("test");
    }
}
public class MyApp {
    public static void main(String[] args) {
        //(1)创建对象
        InnerInterface innerInterface = new InnerInterfaceImpl();
        innerInterface.inner();

        //(2)匿名内部类
        InnerInterface innerInterface1 = new InnerInterface() {
            @Override
            public void inner() {
                System.out.println("test1");
            }
        };
        innerInterface1.inner();
    }
}

 

  还可用把接口的实现放在类里面,这样就相当于一个内部类,所以调用就需要依赖外部类对象来调用

public class MyApp2 {

    public class InnerInterfaceImpl implements InnerInterface{
        @Override
        public void inner() {
            System.out.println("test2");
        }
    }

    public static void main(String[] args) {
        MyApp2 myApp2 = new MyApp2();
        MyApp2.InnerInterfaceImpl innerInterface = myApp2.new InnerInterfaceImpl();
        innerInterface.inner();
    }
}

 

3. 局部内部类和匿名内部类访问局部变量

  (1)局部内部类访问局部变量

public class Test01 {
    public static void main(String[] args) {
        new Test01().test(6);
    }
    public void test(int b){
        int a = 10;
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(a);
                System.out.println(b);
                //    System.out.println(a++); 提示错误,变量被final修饰
                //    System.out.println(b++);
            }
        }).start();
    }
}

 

  (2)匿名内部类访问局部变量

public class Test03 {
    private int age = 12;
    public static void main(String[] args) {
        new Test03().test(20);
    }

    public void test(int x){
        class InnerClass{
            public void InPrint(){
            //    System.out.println(x++); 提示错误,变量被final修饰
                System.out.println(x);
                System.out.println(age++);  //可以访问成员变量
            }
        }
        new InnerClass().InPrint();
    }
}

  总结:

    在Java 1.8后虽然在类中不用直接在变量前使用final修饰,但是也不能修改变量的值,对变量进行++会有编译报错。通过反编译.class文件后,也能看到变量会被final修饰

  所以局部内部类和匿名内部类访问局部变量时会被final修饰

   内部类和外部类是处于同一级别的,内部类不会因为定义在方法中就会随着方法的执行完毕被销毁。

  所以当外部类的方法结束后,局部变量就应该被销毁了,但是内部类可能还会存在,这样内部类就会引用了不存在的变量。此时就需要将局部变量复制一份作为内部类的成员变量,这样局部变量死亡后,内部类依然可以访问它,实际访问的是局部变量的“copy”,相当于延长了局部变量的生命周期。

  将局部变量复制作为内部类的成员变量时,就必须要保证两个变量是一致的,如果在内部类修改了成员变量,方法中也就要改变,所以可以把局部变量设置为final,对它初始化后,就不再改变这个变量了,就可以保证内部类的成员变量和方法的局部变量的一致性了,这实际上也是一种妥协,使得局部变量和内部类的建立的拷贝保持一致。

posted on 2021-12-17 09:43  homle  阅读(543)  评论(0编辑  收藏  举报