Java基础内部类与Static,final

成员内部类,局部内部类,匿名内部类

非 静态成员内部类

public class InnerClassDemo {
    public static void main(String[] args) {
        InnerClassDemo innerClassDemo = new InnerClassDemo();
    }
     class TestDemo {
    }
}

非 静态成员内部类反编译class

public class InnerClassDemo{
    class TestDemo{
        final InnerClassDemo this$0;
        TestDemo(){
            this.this$0 = InnerClassDemo.this;
            super();
        }
    }
    public InnerClassDemo(){
    }
    public static void main(String args[]){
        InnerClassDemo innerClassDemo = new InnerClassDemo();
    }
}

静态内部类

public class InnerClassDemo {
    public static void main(String[] args) {
        InnerClassDemo innerClassDemo = new InnerClassDemo();
    }

    static class TestDemo {
    }
}

静态内部类反编译class

public class InnerClassDemo{
    static class TestDemo{
        TestDemo(){
        }
    }

    public InnerClassDemo(){
    }
    public static void main(String args[]){
        InnerClassDemo innerClassDemo = new InnerClassDemo();
    }
}

1.对比看的很清楚,编译器自动帮我们添加了无参的构造方法
2.非静态的成员内部类持有了外部类的引用

我们知道,静态方法是不能用this关键字的,this表示的是当前对象,
其实可以这么理解,静态的是类级别的,所以不能用this
内部类加static有什么区别,有什么好处?

静态内部类不依赖外部类,普通内部类与外部类之间是相互依赖的关系,
内部类实例不能脱离外部类实例,也就是说它们会同生同死,一起声明,
一起被垃圾回收器回收。
而静态内部类是可以独立存在的,即使外部类消亡了,静态内部类还是可以存在的。

普通内部类不能声明static的方法和变量 普通内部类不能声明static的方法和变量,
注意这里说的是变量,常量(也就是final static修饰的属性)还是可以的,而静态内部类形似外部类,
没有任何限制。

局部内部类,局部内部类不允许静态修饰

public class InnerClassDemo {
    int i;

    public static void main(String[] args) {
        InnerClassDemo innerClassDemo = new InnerClassDemo();
        innerClassDemo.show();
    }

    public void show() {

        class TestDemo {
            public void showInner() {
                System.out.println(i);
            }
        }

        TestDemo testDemo = new TestDemo();
        testDemo.showInner();
    }
}

局部内部类反编译

public class InnerClassDemo{
    int i;
    public InnerClassDemo(){
    }

    public static void main(String args[]){
        InnerClassDemo innerClassDemo = new InnerClassDemo();
        innerClassDemo.show();
    }

    public void show(){
        class 1TestDemo{
            final InnerClassDemo this$0;
            public void showInner(){
                System.out.println(i);
            }

            1TestDemo(){
                this.this$0 = InnerClassDemo.this;
                super();
            }
        }
        1TestDemo testDemo = new 1TestDemo();
        testDemo.showInner();
    }
}

匿名内部类

public class InnerClassDemo {

    public static void main(String[] args) {
        InnerClassDemo innerClassDemo = new InnerClassDemo();
        innerClassDemo.show();
    }

    public void show() {
        final int i = 10;

        new TestDemo1() {
            @Override
            public void showInner() {
                System.out.println(i);
            }
        }.showInner();
    }
}

abstract class TestDemo1 {
    public abstract void showInner();
}

匿名内部类反编译

public class InnerClassDemo{
    abstract class TestDemo{
        final IntegerTest this$0;

        public abstract void showInner();

        TestDemo(){
            this.this$0 = IntegerTest.this;
            super();
        }
    }
    public InnerClassDemo(){
    }

    public static void main(String args[]){
        InnerClassDemo innerClassDemo = new InnerClassDemo();
        innerClassDemo.show();
    }

    public void show(){
        final int i = 10;
        (new TestDemo() {

            final IntegerTest this$0;

            public void showInner(){
                System.out.println(10);
            }

            {
                this.this$0 = IntegerTest.this;
                super();
            }
        }).showInner();
    }
}

局部内部类访问成员变量不需要加final修饰,为啥访问局部变量需要加final修饰?
可以从生命周期的角度来解释
因为局部变量的生命周期是随着方法的调用是消失,而局部内部类可以理解为对象
当show方法调用完毕后,变量i的生命周期就结束了,而匿名对象的生命周期可能还未结束

那么在showInner()方法中访问变量i就变成了不可能了,但是要达到效果 应该怎么做,
Java采用了复制的手段来解决这个问题

如果局部变量的值在编译期间就可以确定,则直接在匿名内部里面创建一个拷贝。
如果局部变量的值无法在编译期间确定,则通过构造器传参的方式来对拷贝进行初始化赋值

但是这样会引来另外一个问题,如果在showInner()方法中改变i的值,会导致什么问题?

会出现数据不一致,这样就达不到以前的目的了,所以为了解决这个问题,Java编译器必须限定变量i为final变量,不允许对变量i进行改变(对于引用类型的变量,是不允许指向新的对象)

你可能感兴趣的:(Java基础内部类与Static,final)