Java冷知识(三)编译器的花招之synthetic修饰符

首先我们应该达成一个共识:很多的Java语法糖都是编译器赋予的,而JVM是一个与Java语言解耦的平台。有了这个共识,再来看今天的主角:synthetic修饰符。

我们在阅读JDK反射包源码时,会遇到isSynthetic()方法,其实现之一是Modifier.isSynthetic(getModifiers()),其他实现方式的原理一样。Modifier是专门定义修饰符的类,其中static final int SYNTHETIC = 0x00001000 表明synthetic是修饰符的一种。
我尝试用synthetic来修饰自定义的Class/Field/Method/Constructer。但是都会编译失败,理由是不认识synthetic修饰符。那么synthetic到底是怎么使用的呢?

官方定义

我从Java语言规范中找到了定义:
Any constructs introduced by the compiler that do not have a corresponding construct in the source code must be marked as synthetic ,except for default constructs and the class initialization method.
意思大概是这样:任何被编译器引入的构造器在源代码中没有一个相应的构造器,那么该段代码就必须要被标记为synthetic的(复合的),除了默认的构造器和类初始化方法。

验证

基于上面的定义,我们知道synthetic是由编译器生成的,而且synthetic有复合的、合成的意思。所以猜测是否是用在内部类中的。我们先构造一个内部类:

public  class SyntheticDemo {

    public static void main(String[] args) {

        InnerClass innerObject = new InnerClass();
        System.out.println("inner: " + innerObject.inner);
    }

    private static class InnerClass{

        private String inner = "我在内部";
    }
}

编译后生成了三个文件:

  • SyntheticDemo$1.class
  • SyntheticDemo$InnerClass.class
  • SyntheticDemo.class

我们依次反编译一下这三个class文件

SyntheticDemo$1.class

javap SyntheticDemo$1.class:

Compiled from "SyntheticDemo.java"
class compiler.SyntheticDemo$1 {
}

javap -v SyntheticDemo$1.class

  Last modified 2019-12-12; size 205 bytes
  MD5 checksum 942560dec8fdbc3d9b65e31e4b41295a
  Compiled from "SyntheticDemo.java"
class compiler.SyntheticDemo$1
  minor version: 0
  major version: 52
  flags: ACC_SUPER, ACC_SYNTHETIC
Constant pool:
   #1 = Class              #7             // compiler/SyntheticDemo$1
   #2 = Class              #9             // java/lang/Object
   #3 = Utf8               SourceFile
   #4 = Utf8               SyntheticDemo.java
   #5 = Utf8               EnclosingMethod
   #6 = Class              #10            // compiler/SyntheticDemo
   #7 = Utf8               compiler/SyntheticDemo$1
   #8 = Utf8               InnerClasses
   #9 = Utf8               java/lang/Object
  #10 = Utf8               compiler/SyntheticDemo
{
}
SourceFile: "SyntheticDemo.java"
EnclosingMethod: #6.#0                  // compiler.SyntheticDemo
InnerClasses:
     static #1; //class compiler/SyntheticDemo$1

这个类里面什么都没有,并且此类的flags包含ACC_SYNTHETIC。

SyntheticDemo$InnerClass.class

javap SyntheticDemo$InnerClass.class:

Compiled from "SyntheticDemo.java"
class compiler.SyntheticDemo$InnerClass {
  compiler.SyntheticDemo$InnerClass(compiler.SyntheticDemo$1);
  static java.lang.String access$100(compiler.SyntheticDemo$InnerClass);
}

javap SyntheticDemo$InnerClass.class:

Classfile /D:/idea_workspace/mycode/target/classes/compiler/SyntheticDemo$InnerClass.class
  Last modified 2019-12-12; size 763 bytes
  MD5 checksum f13a4310236918575d26a2909aa8507e
  Compiled from "SyntheticDemo.java"
class compiler.SyntheticDemo$InnerClass
  minor version: 0
  major version: 52
  flags: ACC_SUPER
Constant pool:
   #1 = Fieldref           #5.#26         // compiler/SyntheticDemo$InnerClass.inner:Ljava/lang/String;
   #2 = Methodref          #5.#27         // compiler/SyntheticDemo$InnerClass."<init>":()V
   #3 = Methodref          #6.#27         // java/lang/Object."<init>":()V
   #4 = String             #28            // 我在内部
   #5 = Class              #30            // compiler/SyntheticDemo$InnerClass
   #6 = Class              #31            // java/lang/Object
   #7 = Utf8               inner
   #8 = Utf8               Ljava/lang/String;
   #9 = Utf8               <init>
  #10 = Utf8               ()V
  #11 = Utf8               Code
  #12 = Utf8               LineNumberTable
  #13 = Utf8               LocalVariableTable
  #14 = Utf8               this
  #15 = Utf8               InnerClass
  #16 = Utf8               InnerClasses
  #17 = Utf8               Lcompiler/SyntheticDemo$InnerClass;
  #18 = Class              #32            // compiler/SyntheticDemo$1
  #19 = Utf8               (Lcompiler/SyntheticDemo$1;)V
  #20 = Utf8               x0
  #21 = Utf8               Lcompiler/SyntheticDemo$1;
  #22 = Utf8               access$100
  #23 = Utf8               (Lcompiler/SyntheticDemo$InnerClass;)Ljava/lang/String;
  #24 = Utf8               SourceFile
  #25 
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值