求模糊矩阵合成运算的程序_合成的

本文探讨了JVM如何处理不同语言编译的字节码,特别是Java中关于类构造函数的合成行为。Java编译器为嵌套类生成具有默认包可见性的额外构造函数,这一特性可以通过反射API观察到。此外,还提到了其他JVM语言如Kotlin如何利用合成方法。虽然日常开发中不一定需要深入理解这些细节,但对于理解和解析反射结果有所帮助。
摘要由CSDN通过智能技术生成

求模糊矩阵合成运算的程序

JVM上运行着多种语言,从JavaClojureJRuby 。 它们都有不同的语法,但是它们都编译为相同的字节码真是太棒了。 JVM将它们全部结合在一起。 当然,它偏向Java,但是即使在Java中, 字节码中也发生了一些不可思议的事情。

最著名的把戏来自以下代码:

publicclassFoo{
    staticclassBar{
        privateBar(){}
    }

    publicstaticvoidmain(String...args){
        newBar();
    }
}

您能猜出Bar类有多少个构造函数?

二。 是的,你读得很好。 对于JVM, Bar类声明2个构造函数。 如果您不相信,请运行以下代码:

Class<Foo.Bar>clazz=Foo.Bar.class;
Constructor<?>[]constructors=clazz.getDeclaredConstructors();
System.out.println(constructors.length);
Arrays.stream(constructors).forEach(constructor->{
    System.out.println("Constructor: "+constructor);
});

输出如下:

Constructor: private Foo$Bar()
Constructor: Foo$Bar(Foo$1)

原因是有据可查的字节码了解访问修饰符,但不了解嵌套类。 为了使Foo类能够创建新的Bar实例,Java编译器会生成一个具有默认包可见性的附加构造函数。

可以使用javap工具确认。

javap-v out/production/synthetic/Foo \$ Bar.class

输出以下内容:

[...]
{
  Foo$Bar(Foo$1);
    descriptor: (LFoo$1;)V
    flags: ACC_SYNTHETIC
    Code:
      stack=1, locals=2, args_size=2
         0: aload_0
         1: invokespecial #1                  // Method "<init>":()V
         4: return
      LineNumberTable:
        line 2: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   LFoo$Bar;
            0       5     1    x0   LFoo$1;
}
[...]

注意ACC_SYNTHETIC标志。 转到JVM规范会产生以下信息:

ACC_SYNTHETIC标志指示此方法是由编译器生成的,并且不会出现在源代码中,除非它是第4.7.8节中指定的方法之一。
—类文件格式
https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6
从理论上讲,应该可以调用此生成的构造函数-尽管不可能提供Foo $ 1的实例,但我们将其放在一边。 但是IDE似乎无法发现这第二个无参数的构造函数。 我没有在Java语言规范中找到任何参考,但是合成类和成员不能直接访问,只能通过反射访问。

在这一点上,人们可能想知道为什么所有关于合成标志的大惊小怪。 它是Java引入的,用于解决嵌套类访问的问题。 但是其他JVM语言使用它来实现其规范。 例如,Kotlin使用合成方法来访问伴随对象:

classBaz(){
    companionobject{
        valBAZ="baz"
    }
}

.class文件上执行javap返回以下输出(出于可读性目的而被删节):

{
  public static final Baz$Companion Companion;
    descriptor: LBaz$Companion;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL

  public Baz();
  [...]

  public static final java.lang.String access$getBAZ$cp();
    descriptor: ()Ljava/lang/String;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
    Code:
      stack=1, locals=0, args_size=0
         0: getstatic     #22                 // Field BAZ:Ljava/lang/String;
         3: areturn
      LineNumberTable:
        line 1: 0
    RuntimeInvisibleAnnotations:
      0: #15()
}
[...]

注意access$getBAZ$cp()静态方法吗? 那就是应该从Java调用的方法的名称:

public class FromJava {

    public static void main(String... args) {
        Baz.Companion.getBAZ();
    }
}

结论

尽管在JVM开发人员的日常工作中不需要了解synthetic标志,但了解反射API返回的一些结果可能会有所帮助。

翻译自: https://blog.frankel.ch/synthetic/

求模糊矩阵合成运算的程序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值