内部类隐式持有外部类

Posted 清浅岁月

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了内部类隐式持有外部类相关的知识,希望对你有一定的参考价值。

内部类隐式持有外部类

源码

package com.example.testdemo;

public class OutClass 
    int  out =2;
    public class InnerClass
        int in=1;
    



编译成.class文件,有两个文件

内部类InnerClass

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.example.testdemo;

public class OutClass$InnerClass 
    int in;


	// 构造方法需要传入OutClass这个对象
    public OutClass$InnerClass(OutClass var1) 
        this.this$0 = var1;
        this.in = 1;
    



外部类:OutClass

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.example.testdemo;

public class OutClass 
    int out = 2;

    public OutClass() 
    

    public class InnerClass 
        int in = 1;

        public InnerClass() 
        
    

静态内部类

看一下加了static的静态内部类是什么样子:

源码

package com.example.testdemo;

public class OutClass 
    int  out =2;
    public static class InnerClass
        int in=1;
    



编译成.class文件,有两个文件

InnerClass内部类

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.example.testdemo;

public class OutClass$InnerClass 
    int in = 1;

    public OutClass$InnerClass() 
    


OutClass外部类

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.example.testdemo;

public class OutClass 
    int out = 2;

    public OutClass() 
    

    public static class InnerClass 
        int in = 1;

        public InnerClass() 
        
    


总结:

1.内部类编译成.class文件后,构造方法需要传递外部类进来,this.this=外部类,导致内部类持有一个外部类。

2.内部类被static后,没有该参数,所以内部类不再持有

内部类和静态内部类的加载

package com.example.testdemo;

import java.util.Random;

public class OutClass 

    public static long OUTER_DATE = System.currentTimeMillis();

    static 
        System.out.println("外部类静态块加载时间:" + System.currentTimeMillis());
    

    public OutClass() 
        System.out.println("外部类构造时间:" + System.currentTimeMillis());

    

    public static class InnerStaticClass 
        public static long INNER_STATIC_DATE = System.currentTimeMillis();

    

    class InnerClass 
        public long INNER_DATE = 0;

        public InnerClass() 
            INNER_DATE = System.currentTimeMillis();
        
    


    public static void outerStaticMethod() 
        System.out.println("外部类静态方法执行了");
    





  timeElapsed();
 System.out.println("打印时间:" + System.currentTimeMillis() + ".....静态内部类加载时间:" +   OutClass.InnerStaticClass.INNER_STATIC_DATE);
 timeElapsed();
 System.out.println("打印时间:" + System.currentTimeMillis() + ".....外部类静态变量加载时间:" + OutClass.OUTER_DATE);
 timeElapsed();
 System.out.println("打印时间:" + System.currentTimeMillis() + ".....调用外部静态方法:" ) ;OutClass.outerStaticMethod();
 timeElapsed();
 OutClass student1 = new OutClass();
 System.out.println("打印时间:" + System.currentTimeMillis() + ".....非静态内部类加载时间:" + student1.new InnerClass().INNER_DATE);

	

执行时间


System.out: 打印时间:1599647679473.....静态内部类加载时间:1599647679473

System.out: 外部类静态块加载时间:1599647680938
System.out: 打印时间:1599647680938.....外部类静态变量加载时间:1599647680938
\\

System.out: 打印时间:1599647682310.....调用外部静态方法:
System.out: 外部类静态方法执行了

System.out: 外部类构造时间:1599647683675
System.out: 打印时间:1599647683675.....非静态内部类加载时间:1599647683675

总结:

静态变量,静态方法,静态块等都是类级别的属性,而不是单纯的对象属性。他们在类第一次被使用时被加载(记住,是一次使用,不一定是实例化)。我们可以简单得用 类名.变量 或者 类名.方法来调用它们。与调用没有被static 修饰过变量和方法不同的是:一般变量和方法是用当前对象的引用(即this)来调用的,静态的方法和变量则不需要。从一个角度上来说,它们是共享给所有对象的,不是一个角度私有。这点上,静态内部类也是一样的。

静态内部类的加载过程:
静态内部类的加载不需要依附外部类,在使用时才加载

所以静态holder的单例:

package com.example.testdemo;

public class SingleInstence 

    private SingleInstence() 
        //  防止反射入侵外部类
        if (SingleInstenceHolder.mSingleInstence != null) 
            throw new IllegalStateException();
        
    

    public static SingleInstence instence() 
        return SingleInstenceHolder.mSingleInstence;
    

    private static class SingleInstenceHolder 
        private static final SingleInstence mSingleInstence = new SingleInstence();
    



以上是关于内部类隐式持有外部类的主要内容,如果未能解决你的问题,请参考以下文章

Android内存泄漏的本质原因解决办法操作实例

Java内部类持有外部类的引用详细分析与解决方案

将类隐式转换为 int 的正确方法是啥?

java中,匿名内部类可以使用外部类的成员变量吗

“全栈2019”Java第七十五章:内部类持有外部类对象

如何将我的类隐式转换为另一种类型?