Java synthetic
读完这篇文章你将会收获到
synthetic fields
synthetic method
synthetic class
概述
上一篇 Java 枚举 提及到编译成 class
文件之后、编译器会在枚举类里帮我们生成一个 VALUES
的静态数组 , 这种编译器生成的都有一个 flag
叫做 synthetic
那么 synthetic
的定义是什么、什么情况下才会有这个 flag
?
由编译器生成的,在源代码中没有出现的,都会被标记为
synthetic
。当然有一些例外的情况:默认的构造函数、类的初始化方法、以及枚举类中的value
和valueOf
方法
synthetic fields
非常常见的一个例子
public class Father {
class Son {
}
}
我们都知道在一个内部类中,可以直接访问外部类的属性和方法,因为在内部类中是存在一个外部类的一个引用变量,而这个引用变量即是编译器帮我们生成的、也就是一个 synthetic
的属性
我们再写一个测试来验证下
Class<Father.Son> clazz = Father.Son.class;
Field[] declaredFields = clazz.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField.getName() + ":" + declaredField.isSynthetic());
}
this$0:true
我们再来验证一下上一篇文章 Java 枚举 的枚举类
Class<BehaviorEnum> clazz = BehaviorEnum.class;
Field[] declaredFields = clazz.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField.getName() + ":" + declaredField.isSynthetic());
}
FOLLOW:false
WOW:false
FORWARD_TO_FRIENDS:false
ADD_TO_FAVORITES:false
$VALUES:true
synthetic method
我们再来看看被 synthetic
修饰的方法吧
public class Father {
class Son {
private String name;
}
/**
* just for test synthetic
* @return
*/
public String getName() {
// just for test synthetic
return new Son().name;
}
}
在 Son
类中突然多出了这么一个方法。因为其实 name
属性是一个私有方法、外部类 Father
中却能直接访问这个属性、对于我们写代码来说、这是非常合理的一个事情、但是这都是编译器默默的付出、为我们生成了一个静态的 package
范围的方法、参数就是 Son
的实例、返回值就是 String
Class<Father.Son> sonClass = Father.Son.class;
Method[] declaredMethods = sonClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(
Modifier.toString(declaredMethod.getModifiers()) +
":" + declaredMethod.getName() +
":" + declaredMethod.isSynthetic());
}
static:access$000:true
synthetic class
我们再来看看被 synthetic
修饰的 class
public class Father03 {
public Son generateSon() {
return new Son();
}
private class Son{
}
}
然后我们编译为 class
文件
发现多出来一个匿名类 Father03$1.class
这个是什么鬼鬼
这个类完全是一个空的类、父类直接是 Object
、也没额外定义一些自己的方法
我们再看看 Father03$Son.class
发现它居然有两个构造方法,一个带参数的 package scope 的构造参数是编译器生成的。参数是 Father03
和 Father03$1
我们再看看 Father03
里面的 generateSon
方法
发现它调用的是那个带参数的构造方法,并且参数 Father03$1
的值是为 null
的
根据上面的种种信息来看、我们可以这么认为、对于一个 private
的内部类(其构造函数默认也是 private
) , 外部类也是无法直接去创建它的实例的、其实换句话来说、对于类的定义来说、不管你是作为一个内部类定义在另一个类中、还是单独定义在一个 java
文件,java
的可见性都是起效的。至于为啥可以在外部内直接创建一个 private 的类的实例、无外乎就是 java 编译器帮我们做了一些额外的工作。
回到上面的例子中、因为 Father03$Son
. 只有一个私有的构造函数、而为了能在 Father03
中去创建这么一个 Father03$Son
对象,编译器不得不为我们生成一个 package scope
的构造函数、而午餐的构造函数已经存在了、那编译器只能创建一个有参的构造函数啊、那么问题来了、这个参数的类型应该是啥、那就生成一个类呗、专门为这个参数用。而调用这个构造函数的时候、就直接传给 null
值给它
所以说 Father03$1
作用无外乎可能就是作为一个参数的类型被用到
相关文章
Java synthetic的更多相关文章
- Javac语法糖之TryCatchFinally
https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.20.3 Optionally replace a try s ...
- Spark案例分析
一.需求:计算网页访问量前三名 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} /* ...
- Java 中冷门的 synthetic 关键字原理解读
看JAVA的反射时,看到有个synthetic ,还有一个方法isSynthetic() 很好奇,就了解了一下: 1.定义 Any constructs introduced by a Java co ...
- Java中的synthetic
有synthetic标记的field和method是class内部使用的,正常的源代码里不会出现synthetic field.小颖编译工具用的就是jad.所有反编译工具都不能保证完全正确地反编译cl ...
- 《深入理解Java虚拟机》类文件结构
上节学习回顾 在上一节当中,主要以自己的工作环境简单地介绍了一下自身的一些调优或者说是故障处理经验.所谓百变不离其宗,这个宗就是我们解决问题的思路了. 本节学习重点 在前面几章,我们宏观地了解了虚拟机 ...
- Java内部类final语义实现
本文描述在java内部类中,经常会引用外部类的变量信息.但是这些变量信息是如何传递给内部类的,在表面上并没有相应的线索.本文从字节码层描述在内部类中是如何实现这些语义的. 本地临时变量 基本类型 fi ...
- (9) 深入了解Java Class文件格式(八)
转载:http://blog.csdn.net/zhangjg_blog/article/details/22205831 在本专栏的第一篇文章 深入理解Java虚拟机到底是什么 中, 我们主要讲解了 ...
- 使用Proguard做Java代码混淆
下载Proguard, 我下的是最新的Proguad5.2 在windows下运行bin/proguardgui.bat, 可以看见图形界面, 载入配置, 然后process. 配置文件例子 -inj ...
- 使用proguard混淆java web项目代码
1.首先下载proGuard.zip到本地: proguard4.5beta4.tar.zip解压开,2.新建文本文档,修改文件名为XXX.pro,然后复制下面内容到.pro -injars 'Y:\ ...
随机推荐
- Java实现 LeetCode 789 逃脱阻碍者(曼哈顿距离)
789. 逃脱阻碍者 你在进行一个简化版的吃豆人游戏.你从 (0, 0) 点开始出发,你的目的地是 (target[0], target[1]) .地图上有一些阻碍者,第 i 个阻碍者从 (ghost ...
- (Java实现) 整数区间
一.题目描述 给n个区间,形式为[a, b],a和b均为整数,且a < b. 求一个最小的整数点的集合,使得每个区间至少2个不同的元素(整数点)属于这个集合. 求这个集合的元素个数. 输入 第1 ...
- Java实现 LeetCode 447 回旋镖的数量
447. 回旋镖的数量 给定平面上 n 对不同的点,"回旋镖" 是由点表示的元组 (i, j, k) ,其中 i 和 j 之间的距离和 i 和 k 之间的距离相等(需要考虑元组的顺 ...
- Java实现 LeetCode 391 完美矩形
391. 完美矩形 我们有 N 个与坐标轴对齐的矩形, 其中 N > 0, 判断它们是否能精确地覆盖一个矩形区域. 每个矩形用左下角的点和右上角的点的坐标来表示.例如, 一个单位正方形可以表示为 ...
- Java实现 蓝桥杯VIP 算法训练 数组查找及替换问题
描述 给定某整数数组和某一整数b.要求删除数组中可以被b整除的所有元素,同时将该数组各元素按从小到大排序.如果数组元素数值在A到Z的ASCII之间,替换为对应字母.元素个数不超过100,b在1至100 ...
- 一文带你快速搞懂动态字符串SDS,面试不再懵逼
目录 redis源码分析系列文章 前言 API使用 embstr和raw的区别 SDSHdr的定义 SDS具体逻辑图 SDS的优势 更快速的获取字符串长度 数据安全,不会截断 SDS关键代码分析 获取 ...
- Java与Swift对比
本文链接:http://blog.csdn.net/msyqmsyq/article/details/53538159 从Java到Swift还是比较简单的,相比Object-C,Swift和Java ...
- java第三阶段作业总结
Java第三阶段总结 前言 到这里,Java课程学习进入了尾声,在这学习过程中,我学习到很多,也发现了自己的很多不足,这篇博客主要针对的是Java整门课程学习的总结. 课程收获 对整门课程的学习,我有 ...
- throws,throw,try,catch,finally 分别代表什么 意义?
Java通过面向对象的方法进行异常处理,把各种不同的异常进行分类,并提供了良好的接口. 在Java中,每个异常都是一个对象,它是Throwable类或其它子类的实例.当一个方法出现异常后便 抛出一个异 ...
- Censoring【KMP算法+堆栈模拟】
Censoring 传送门:链接 来源:UPC8203 题目描述 Farmer John has purchased a subscription to Good Hooveskeeping ma ...