javap反编译解释外部类直接使用内部类private字段的原理
2016-07-04 15:56:39
我们都知道:
1、内部类可以直接访问外部类的private字段和方法;
2、非静态内部类持有外部类的引用;
3、外部类可以直接访问内部类的private字段和方法(不管是不是静态内部类);
最近看到一篇文章,大意是讨论这个的,处于好奇,想从字节码的角度研究一下原因,于是有此文。
1、关于javap命令:
"The javap command disassembles one or more class files. The output depends on the options used. When no options are used, then the javap command prints the package, protected and public fields, and methods of the classes passed to it. The javap command prints its output to stdout".
来及Oracle官网的解释,大意是:javap命令用来反汇编一个或多个class文件,输出结果取决于你是用的参数。在不使用任何参数的情况下,javap命令打印出package, protected and public修饰的变量以及传给该类的方法。javap命令将输出打印到stdout。
说白了,javap是JDK提供的一个反汇编的命令,可以将字节码文件反汇编成我们能看懂的代码。
2、先上一段源码:

使用到的命令:
javap -c Test\$A //反编译内部类,这条命令中反斜杠“\”必须得有,否则反编译的结果不正常
javap -verbose Test //反编译主类Test
3、非静态内部类A的反编译结果:

private修饰的字段在字节码中并不是一个独立的字段,而是用access102()方法来替代的,这样做的目的就是为了不破坏private属性的作用和设计。同时解释了为什么非静态内部类持有外部类的引用,编译器给非静态内部类A添加了一个构造方法Test$A,传入了外部类引用作为参数,而且定义了一个外部类引用字段this$0。
4、静态内部类B的反编译结果:

对private字段的直接使用方式和非静态内部类是一样的,但是构造器没有传入外部类引用作为参数,同时也没有定义外部类引用this$0。
可见,外部类可以直接访问内部类的private修饰的字段和方法其实是一种假象,毕竟如果真能这样,那么private的设计完整性如何保证呢?此外,关于非静态内部类如何持有外部类引用的原理,想必也应该清楚了。
5、匿名内部类的反编译结果

如图,匿名内部类实现了接口Inter,编译器给匿名内部类添加了构造器,同时传入了外部类的引用。
所以,匿名内部类也是默认持有外部类的引用的。
javap反编译解释外部类直接使用内部类private字段的原理的更多相关文章
- 震惊!外部类可以访问内部类private变量
在讲Singleton时我举例时用过这样一段代码: public class SingletonDemo { private static class SingletonHolder{ private ...
- Java外部类可以访问内部类private变量
在讲Singleton时我举例时用过这样一段代码: public class SingletonDemo { private static class SingletonHolder{ private ...
- Java中String的intern方法,javap&cfr.jar反编译,javap反编译后二进制指令代码详解,Java8常量池的位置
一个例子 public class TestString{ public static void main(String[] args){ String a = "a"; Stri ...
- 使用javap反编译class文件
一个普通的Java类: package org.ccnt.concurrence; public class VolatileTest { public static volatile int rac ...
- @使用javap反编译Java字节码文件
在Sun公司提供的JDK中,就已经内置了Java字节码文件反编译工具javap.exe(位于JDK安装目录的bin文件夹下). 我们可以在dos窗口中使用javap来反汇编指定的Java字节码文件.在 ...
- IDEA设置External Tools之Javap反编译字节码
通过Jdk的命令javap可以反编译查看字节码,但是在使用idea的时候一直用命令行去操作不太好操作,而且因为idea会把class码 放在target里面,经常会忘记切换目录.这个时候idea的Ex ...
- Java通过继承外部类来建立该外部类的protected内部类的实例(转)
原文链接:http://blog.sina.com.cn/s/blog_7de00ff60102xffx.html 如果想要在外部类的导出类(子类)中建立该外部类的为protected权限的内部类的实 ...
- Java的外部类为什么不能使用private、protected进行修饰
对于顶级类(外部类)来说,只有两种修饰符:public和默认(default).因为外部类的上一单元是包,所以外部类只有两个作用域:同包,任何位置.因此,只需要两种控制权限:包控制权限和公开访问权限, ...
- javap反编译命令详解&Eclipse中配置javap命令
javap命令所有参数如下图所示: javap 命令用于解析类文件.其输出取决于所用的选项.若没有使用选项,javap 将输出传递给它的类的 public 域及方法.javap 将其输出到标准输出设备 ...
随机推荐
- Overload和Override的区别
Overload:重载 |- 在一个类中定义的若干方法 |- 所有的方法名相同,但参数类型或个数不同 |- 只有参数有关,与返回类型无关 Override:覆写 |- 在继承的关系中 |- 子类定义了 ...
- Arduino 极速入门系列 - 光控灯(3) - 光敏电阻、与电阻分压那些事
继续是讲解基础原理,新手专用部分.这次讲光敏电阻,和用电阻分压.光电元器件有好几种,其中测光相关的元器件,常见的有光敏三极管和光敏电阻,我们这次光控灯用光敏电阻.在我们光控灯里面,将会使用它搭建出分压 ...
- nginx基本配置和参数说明
#运行用户user nobody;#启动进程,通常设置成和cpu的数量相等worker_processes 1; #全局错误日志及PID文件#error_log logs/error.log;#err ...
- Docker常见问题解决
一.Docker中运行ubuntu容器,字体颜色太深导致无法看清 解决方案: 1. 利用dircolors命令,查看我们的系统当前的文件名称显示颜色的值,然后利用管道重定向到用户目录下的任意一个文件( ...
- Android单例线程池
package com.jredu.schooltong.manager; import java.util.concurrent.ExecutorService;import java.util.c ...
- NSScanner知悉 (转)
http://blog.csdn.net/likendsl/article/details/7974761 NSScanner是一个类,用于在字符串中扫描指定的字符,尤其是把它们翻译/转换为数字和别的 ...
- HTML <a> download 属性,点击链接来下载图片
Html5里面的 标签的 Download 属性可以设置一个值来规定下载文件的名称.所允许的值没有限制,浏览器将自动检测正确的文件扩展名并添加到文件 (.img, .pdf, .txt, .html, ...
- Oracle SQL explain/execution Plan
From http://blog.csdn.net/wujiandao/article/details/6621073 1. Four ways to get execution plan(anyti ...
- Ubuntu16.04安装Samba
在新装的ubuntu16.04下安装samba. 安装好samba后备份下配置文件: zhuben@zb:~$ sudo apt-get install samba zhuben@zb:~$ cd / ...
- a.redhat系统如何卸载默认jdk
Redhat系统安装之后,会默认有openjdk在安装(下图已经是卸载掉了) 这个openjdk下面的需要进行卸载,你可以通过命令进行卸载,例如首先查看JDK,然后默认直接通过rpm命令进行卸载L 卸 ...