当我们分析内存泄漏的场景时,总会想到不能在内部类中做耗时操作,因为它会持有外部类的因为,导致外部类的实例在生命周期结束的时候没有办法及时释放,这就造成了内存泄漏.

好像这就是一个公理一样,就是人们说着说着就都认可它了,却没有人能说出个为什么.

今天我们就来分析一下为什么吧

首先来看一个例子

public class Outer {

private int count;

//匿名内部类1

private StaticInner si1 = new StaticInner(){

@Override

public void doAction() {

count++;

}

};

private StaticInner si2;

private Inner i3;

public void setInner(StaticInner inner) {

this.si2 = inner;

}

public Outer() {

i3 = new Inner();

//匿名内部类2

setInner(new StaticInner(){

@Override

public void doAction() {

super.doAction();

count++;

}

});

}

public void doAction() {

si1.doAction();

si2.doAction();

i3.doSomething();

}

/**

* 内部类

*/

private class Inner {

public void doSomething() {

count++;

}

}

/**

* 静态内部类

*/

private static class StaticInner{

public void doAction() {

}

}

}

以上代码概述了我们平时写代码时常见的几种内部类和匿名内部类以及静态内部类的写法,并访问了外部类的成员变量,当然静态内部类没法访问,编译器会报错.

然后通过javac命令编译一下.java源文件,得到几个.class字节码文件,这时如果你尝试打开字节码文件,会发现一堆乱码,可以用jd-gui字节码反编译工具打开.

我们可以发现好几个.class文件,一个一个来看

Outer$1.class

class Outer$1

extends Outer.StaticInner

{

Outer$1(Outer paramOuter)

{

super(null);

}

public void doAction()

{

Outer.access$108(this.this$0);

}

}

这个类代表我们声明成员变量si1的匿名内部类,可以看到它继承自静态内部类StaticInner,它还定义了一个构造函数,并传入了内部类的实例作为参数,虽然不知道super(null)具体实现,但是我们知道它要访问paramOuter实例的成员变量,必须得使用它的引用来访问,所以它肯定是持有了外部类实例的引用.

Outer$2.class

class Outer$2

extends Outer.StaticInner

{

Outer$2(Outer paramOuter)

{

super(null);

}

public void doAction()

{

super.doAction();

Outer.access$108(this.this$0);

}

}

这个和上面提到的Outer$1.class类似,所以这两种匿名内部类是没有任何本质区别的,不管是定义成员变量还是方法传参.

Outer$Inner.class

class Outer$Inner

{

private Outer$Inner(Outer paramOuter) {}

public void doSomething()

{

Outer.access$108(this.this$0);

}

}

这是定义的内部类,可以看到编译器也为它单独生成了一个.class文件,构造函数被定义为私有的,且同样传入了外部类的实例,所以它也是持有了外部类实例的引用.

Outer$StaticInner.class

class Outer$StaticInner

{

public void doAction() {}

}

这是静态内部类编译后的字节码文件,编译器并没有为它添加额外的构造函数,所以它其实和我们的外部类没有任何关系,这是写在同一个.java源文件中而已.

分析到这里,应该算可以证明为什么静态内部类会持有外部类的实例了

在分析内存泄漏的时候,它应该是我们应该重点关注的对象.

由此我们也能够明白java代码执行过程并不是我们所看的那样,编译器也做了很多工作.只是这一块我们并不怎么关注.

java内部类为什么会持有外部类的引用_java中内部类为什么会持有外部类的引用?...相关推荐

  1. java 静态内部类 内部类_Java中内部类和静态内部类的区别

    内部类和静态内部类 示例 public class OuterClass { private int numPrivate = 1; public int numPublic = 2; public ...

  2. java字面量和符号引用_java中字面量,常量和变量之间的区别(附:Integer缓存机制)...

    一.引子 在各种教科书和博客中这三者经常被引用,今天复习到内存区域,想起常量池中就是存着字面量和符号引用,其实这三者并不是只在java中才有,各个语言中都有类似的定义,所以做一下总结,以示区分. 二. ...

  3. java 基本类型的引用_Java中的基本数据类型与引用数据类型

    一.基本数据类型 byte.short.int.long(整数类型) float.double(浮点数类型) char(字符型) boolean(布尔类型 ) Java数据大多数存放在堆栈中.栈区:存 ...

  4. java 软引用_Java中弱引用和软引用的区别以及虚引用和强引用介绍

    知道弱引用和软引用的概念与如何使用它们是两码事,引用类在垃圾回收工作的过程中有重要作用.我们都知道垃圾回收器会回收符合回收条件的对象的内存,但并不是所有的程序员都知道回收条件取决于指向该对象的引用类型 ...

  5. java 无法取消引用_Java的新手,并出现错误“无法取消引用int” - java

    我是java的新手,并且已经从事了一段时间,但是仍然收到错误消息:无法取消引用int.我看到了几个类似的问题,但仍然无法弄清自己的情况. 这是完整的代码: package inclass; class ...

  6. java 指针 引用_java中的引用与c中的指针

    指针 首先要弄清楚指针和c中的指针是不一样的,前者是概念,后者是具体实例. 换句话说,C中的指针只是指针中的一种,其他语言也有指针,比如C++.但是我们同别人交流的时候,大都不会从概念上去交流,一般会 ...

  7. java是先有类还是先有对象_Java中关于先有鸡还是先有蛋的问题----ClassObject

    在Java中,我们常常会看到一个类型:Class.并且在类似Person.class,cache.getClass()等代码中见到它的身影. 众所周知,Class是用来描述一个类的类型,而Object ...

  8. java 基本类型 引用_java中 引用类型 和 基本类型 有何区别?

    栈与堆都是Java用来在Ram中存放数据的地方.与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆. Java的堆是一个运行时数据区,类的(对象从中分配空间.这些对象通过new.newa ...

  9. java接口那一节是哪的知识_Java中的接口知识汇总

    Java中的接口知识汇总 发布于 2020-4-29| 复制链接 本文给大家汇总介绍了在java中的接口知识,包括为什么要使用接口.什么是接口.抽象类和接口的区别.如何定义接口以及定义接口注意点,希望 ...

最新文章

  1. 三星s6 android 5.1.1,谷歌亲儿子们痛哭:三星S6都升级安卓5.1.1了!
  2. 随机重命名MP3文件
  3. 成功解决OpenCV Error: Assertion failed (scn == 3 || scn == 4) in cv::cvtColor
  4. 2018年冷链百强_在分析了47,251个依赖关系之后,2016年Java图书馆百强
  5. UNIX(多线程):22---几种常见的线程池
  6. 老是原罪?技术圈为何不待见大龄企业家
  7. myeclipse汉化及其相关配置设置(转)
  8. Div图片垂直居中的方法
  9. centos7安装mysql客户端
  10. kb931125—rootsupd_kb931125补丁下载
  11. 台式计算机找不到无线连接,台式机如何连接wifi_台式机找不到无线网络
  12. 6轴游戏手柄测试python程序
  13. c# chart 点值标注_C# chart控件参数设定总结
  14. 电信行业数据安全风险评估案例 - 数据安全治理之数据安全风险评估白皮书
  15. 电脑常用工具集(开发,windows,持续更新)
  16. VIRTIO-BLK-DATA-PLANE的配置使用
  17. [项目管理-28]:四象限法与任务的时间优先级管理
  18. 背单词的小智 (二分)
  19. 国企招聘:中国空空导弹2023校园招聘正式启动
  20. Log4j2报错ERROR StatusLogger Unrecognized format specifier

热门文章

  1. Python函数(2)
  2. WPF系列学习之三(路由事件)
  3. Java EE开发三剑客现状及发展浅析
  4. wordpress content.php,2020主题:content.php
  5. dods 机器人_胜利之日机器人补丁
  6. JavaScript中的三种常用继承方法
  7. python多线程怎么写日志_Python日志记录在多进程下的使用
  8. hadoop 写入mysql_使用MapReducer将文件写入mysql 数据库
  9. base64还原 java_base64字符串还原成原图片
  10. html如何压缩发送,css如何压缩?