我在玩https://kotlin.github.io/dataframe/overview.html,想看看从Java而不是Kotlin调用看起来有多复杂。我发现很多地方都有javap
输出中显示的方法,例如:
$ javap -cp . org/jetbrains/kotlinx/dataframe/api/GroupByKt.class
Compiled from "groupBy.kt"
public final class org.jetbrains.kotlinx.dataframe.api.GroupByKt {
...
public static org.jetbrains.kotlinx.dataframe.api.GroupBy groupBy$default(org.jetbrains.kotlinx.dataframe.DataFrame, boolean, kotlin.jvm.functions.Function2, int, java.lang.Object);
...
其中最后一个方法名为groupBy$default
。在反编译Kotlin编译器生成的JVM字节码之后,我看到它调用了上面的函数。
但是,Eclipse会抱怨它是未定义的,并且无法编译Java类。Maven也抱怨道:
[ERROR] /prj/ks/KotlinxDataFrameTest.java:[130,21] cannot find symbol
symbol: method groupBy$default(org.jetbrains.kotlinx.dataframe.DataFrame<capture#1 of ?>,boolean,(gb,it)->[...] ""),int,<nulltype>)
location: class org.jetbrains.kotlinx.dataframe.api.GroupByKt
我认为在javap
中出现的任何方法都可以从Java中调用。我错过了什么?
编辑:根据@broot的评论添加了javap -verbose
输出:
public static org.jetbrains.kotlinx.dataframe.api.GroupBy groupBy$default(org.jetbrains.kotlinx.dataframe.DataFrame, boolean, kotlin.jvm.functions.Function2, int, java.lang.Object);
descriptor: (Lorg/jetbrains/kotlinx/dataframe/DataFrame;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/api/GroupBy;
flags: (0x1009) ACC_PUBLIC, ACC_STATIC, ACC_SYNTHETIC
Code:
stack=3, locals=5, args_size=5
0: iload_3
1: iconst_1
2: iand
3: ifeq 8
6: iconst_1
7: istore_1
8: aload_0
9: iload_1
10: aload_2
11: invokestatic #32 // Method groupBy:(Lorg/jetbrains/kotlinx/dataframe/DataFrame;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/api/GroupBy;
14: areturn
StackMapTable: number_of_entries = 1
frame_type = 8 /* same */
LineNumberTable:
line 21: 0
2条答案
按热度按时间qc6wkl3g1#
您不应该能够从普通Java代码调用合成方法。他们是隐藏的。
合成方法是既没有显式声明也没有隐式声明的方法。根据JLS 15.12.1,当你调用一个方法时,你需要给予一个标识符(方法名),“出现在一个具有该名称的方法声明的作用域中”,以解析声明它的类型。合成方法的定义不存在这样的声明。
从直观的Angular 来看,合成方法和字段仅在生成字节码时被注入到代码中。Java编译器在进行语法和语义分析的早期阶段不会知道合成名称……呢
正如@Slaw所指出的,您可以使用反射来定位并调用合成方法;参见What are the interets of synthetic methods?作为示例。同样,您也可以从“字节代码工程”库或类似库注入的代码中调用它们。
然而,合成方法是一个实现工件,并且(理论上)它们可以从一个Java版本更改到下一个版本。因此,编写依赖于调用合成方法的Java代码将是一个坏主意。事实上,Java团队改变Java运行时以使其(更)难以做到这一点并不是不可想象的。就像他们最近使引用内部JDK类等变得困难一样。
pbgvytdp2#
作为KotlinDataFrame库的贡献者,我建议不要为该库使用其他JVM语言。与其他语言的兼容性根本不是优先事项。DataFrame的优势在于Kotlin能够编写简洁的DSL,并且它使用了大量的扩展函数。这将导致不必要的复杂和不可读的Java代码,如果它在所有工作。