读完这篇文章你将会收获到

  • synthetic fields
  • synthetic method
  • synthetic class

概述

上一篇 Java 枚举 提及到编译成 class 文件之后、编译器会在枚举类里帮我们生成一个 VALUES 的静态数组 , 这种编译器生成的都有一个 flag 叫做 synthetic

那么 synthetic 的定义是什么、什么情况下才会有这个 flag ?

由编译器生成的,在源代码中没有出现的,都会被标记为 synthetic。当然有一些例外的情况:默认的构造函数、类的初始化方法、以及枚举类中的 valuevalueOf 方法

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 的构造参数是编译器生成的。参数是 Father03Father03$1

我们再看看 Father03 里面的 generateSon 方法

发现它调用的是那个带参数的构造方法,并且参数 Father03$1 的值是为 null

根据上面的种种信息来看、我们可以这么认为、对于一个 private 的内部类(其构造函数默认也是 private ) , 外部类也是无法直接去创建它的实例的、其实换句话来说、对于类的定义来说、不管你是作为一个内部类定义在另一个类中、还是单独定义在一个 java 文件,java 的可见性都是起效的。至于为啥可以在外部内直接创建一个 private 的类的实例、无外乎就是 java 编译器帮我们做了一些额外的工作。

回到上面的例子中、因为 Father03$Son. 只有一个私有的构造函数、而为了能在 Father03 中去创建这么一个 Father03$Son 对象,编译器不得不为我们生成一个 package scope 的构造函数、而午餐的构造函数已经存在了、那编译器只能创建一个有参的构造函数啊、那么问题来了、这个参数的类型应该是啥、那就生成一个类呗、专门为这个参数用。而调用这个构造函数的时候、就直接传给 null 值给它

所以说 Father03$1 作用无外乎可能就是作为一个参数的类型被用到

相关文章

Java synthetic的更多相关文章

  1. Javac语法糖之TryCatchFinally

    https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.20.3 Optionally replace a try s ...

  2. Spark案例分析

    一.需求:计算网页访问量前三名 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} /* ...

  3. Java 中冷门的 synthetic 关键字原理解读

    看JAVA的反射时,看到有个synthetic ,还有一个方法isSynthetic() 很好奇,就了解了一下: 1.定义 Any constructs introduced by a Java co ...

  4. Java中的synthetic

    有synthetic标记的field和method是class内部使用的,正常的源代码里不会出现synthetic field.小颖编译工具用的就是jad.所有反编译工具都不能保证完全正确地反编译cl ...

  5. 《深入理解Java虚拟机》类文件结构

    上节学习回顾 在上一节当中,主要以自己的工作环境简单地介绍了一下自身的一些调优或者说是故障处理经验.所谓百变不离其宗,这个宗就是我们解决问题的思路了. 本节学习重点 在前面几章,我们宏观地了解了虚拟机 ...

  6. Java内部类final语义实现

    本文描述在java内部类中,经常会引用外部类的变量信息.但是这些变量信息是如何传递给内部类的,在表面上并没有相应的线索.本文从字节码层描述在内部类中是如何实现这些语义的. 本地临时变量 基本类型 fi ...

  7. (9) 深入了解Java Class文件格式(八)

    转载:http://blog.csdn.net/zhangjg_blog/article/details/22205831 在本专栏的第一篇文章 深入理解Java虚拟机到底是什么 中, 我们主要讲解了 ...

  8. 使用Proguard做Java代码混淆

    下载Proguard, 我下的是最新的Proguad5.2 在windows下运行bin/proguardgui.bat, 可以看见图形界面, 载入配置, 然后process. 配置文件例子 -inj ...

  9. 使用proguard混淆java web项目代码

    1.首先下载proGuard.zip到本地: proguard4.5beta4.tar.zip解压开,2.新建文本文档,修改文件名为XXX.pro,然后复制下面内容到.pro -injars 'Y:\ ...

随机推荐

  1. Java实现UVA10131越大越聪明(蓝桥杯每周一题)

    10131越大越聪明(蓝桥杯每周一题) [问题描述] 一些人认为,大象的体型越大,脑子越聪明.为了反驳这一错误观点,你想要分析一组大象的数据,找出尽量 多的大象组成一个体重严格递增但 IQ 严格递减的 ...

  2. Java实现 LeetCode 205 同构字符串

    205. 同构字符串 给定两个字符串 s 和 t,判断它们是否是同构的. 如果 s 中的字符可以被替换得到 t ,那么这两个字符串是同构的. 所有出现的字符都必须用另一个字符替换,同时保留字符的顺序. ...

  3. Java实现 洛谷 P1090 合并果子

    import java.io.BufferedInputStream; import java.util.Arrays; import java.util.Scanner; public class ...

  4. java实现基因牛的繁殖

    基因牛的繁殖 基因牛 张教授采用基因干预技术成功培养出一头母牛,三年后,这头母牛每年会生出1头母牛, 生出来的母牛三年后,又可以每年生出一头母牛.如此循环下去,请问张教授n年后有多少头母牛? 以下程序 ...

  5. Java实现第八届蓝桥杯外星日历

    外星日历 题目描述 某星系深处发现了文明遗迹. 他们的计数也是用十进制. 他们的文明也有日历.日历只有天数,没有年.月的概念. 有趣的是,他们也使用了类似"星期"的概念, 只不过他 ...

  6. jdbc+mysql常见报错总结

    1.The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone. You ...

  7. Flask 的配置文件

    Flask 的配置文件 四种方法给 Flask 做配置 1直接给 app 对象赋值属性 以字典的形式,给flask做配置 以文件的形式,给flask做配置(django 就是用这种) 以类的形式,给f ...

  8. SpringBoot整合分布式ZooKeeper和Dubbo

    ZooKeeper ZooKeeper是一个分布式的,开放远吗的分布式应用程序协调服务.它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护.域名服务.分布式同步.组服务等. 服务提供者 ...

  9. Excel经典教程之一

    照片名称:未命名 照片名称:自动筛选 照片名称:在Excel中字符替换 照片名称:在Excel中直接编辑“宏” 照片名称:在Excel中为导入外部数据 照片名称:在Excel中行列快速转换 照片名称: ...

  10. CentOS7.5搭建Hadoop2.7.6完全分布式集群

    一 完全分布式集群搭建 Hadoop官方地址:http://hadoop.apache.org/ 1  准备3台客户机 1.2 关闭防火墙,设置静态IP,主机名 关闭防火墙,设置静态IP,主机名此处略 ...