美文网首页
Java基础内部类与Static,final

Java基础内部类与Static,final

作者: 青果果 | 来源:发表于2018-06-22 15:22 被阅读0次

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

    非 静态成员内部类

    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

          本文链接:https://www.haomeiwen.com/subject/xqqkyftx.html