Luk*_*der 18 javascript java java-8 nashorn
假设以下API:
package nashorn.test;
public class API {
public static void test(String string) {
throw new RuntimeException("Don't call this");
}
public static void test(Integer... args) {
System.out.println("OK");
}
}
Run Code Online (Sandbox Code Playgroud)
以下Nashorn JavaScript代码段将失败:
var API = Java.type("nashorn.test.API");
API.test(1);
Run Code Online (Sandbox Code Playgroud)
将调用第一种方法而不是第二种方法.这是Nashorn引擎中的一个错误吗?
为了记录,此问题先前已在jOOQ用户组上报告,其中方法重载和varargs被大量使用,并且此问题可能会导致很多麻烦.
可能有人怀疑这可能与拳击有关.它没有.当我这样做时,问题也出现了
public class API {
public static void test(String string) {
throw new RuntimeException("Don't call this");
}
public static void test(Integer... args) {
System.out.println("OK");
}
public static void test(MyType... args) {
System.out.println("OK");
}
}
Run Code Online (Sandbox Code Playgroud)
和:
public class MyType {
}
Run Code Online (Sandbox Code Playgroud)
然后:
var API = Java.type("nashorn.test.API");
var MyType = Java.type("nashorn.test.MyType");
API.test(new MyType());
Run Code Online (Sandbox Code Playgroud)
Att*_*edi 27
作为为Nashorn编写重载解析机制的人,我总是着迷于人们遇到的角落案例.无论好坏,这是最终如何被调用:
Nashorn的重载方法解决方案尽可能模仿Java语言规范(JLS),但也允许特定于JavaScript的转换.JLS表示,在选择调用重载名称的方法时,只有在没有适用的固定arity方法时,才可以考虑使用变量arity方法进行调用.通常,从Java调用时test(String)不适用于带有a的调用int,因此test(Integer...)将调用该方法.但是,由于JavaScript实际上允许数字到字符串的隐式转换,因此它适用于任何变量arity方法之前.因此观察到的行为.Arity胜过非转换.如果添加了一个test(int)方法,则会在String方法之前调用它,因为它是固定的arity,比String更具体.
您可以争辩说我们应该改变选择方法的算法.甚至在Nashorn项目之前就已经有了很多想法(甚至在我独立开发Dynalink时).当前代码(在Nashorn实际构建的Dynalink库中体现)遵循JLS到字母,并且在没有特定于语言的类型转换时将选择与Java相同的方法.然而,一旦你开始放松你的类型系统,事情就会开始微妙地改变,你放松的越多,它们就会变得越多(而且JavaScript会放松很多),对选择算法的任何改变都会有其他一些改变.别人会遇到奇怪的行为......我只是带着轻松的类型系统,我很害怕.例如:
test(String)不被认为适用于int参数),一些JS开发人员会因为需要将程序转换为调用String方法而感到困扰(例如test(String(x)),确保x是字符串等).正如你所看到的,无论我们做什么,其他东西都会受到影响; 重载方法选择在Java和JS类型系统之间处于紧密的位置,并且对逻辑中的微小变化非常敏感.
最后,当您在重载中手动选择时,您也可以坚持使用非限定类型名称,只要参数位置中包名称的潜在方法签名没有歧义,即
API["test(Integer[])"](1);
Run Code Online (Sandbox Code Playgroud)
也应该工作,不需要java.lang.前缀.这可能会缓解语法噪音,除非您可以重新编写API.
HTH,Attila.
这些是有效的解决方法:
test(Integer[])使用数组参数显式调用该方法:var API = Java.type("nashorn.test.API");
API.test([1]);
Run Code Online (Sandbox Code Playgroud)
public class AlternativeAPI1 {
public static void test(Integer... args) {
System.out.println("OK");
}
}
Run Code Online (Sandbox Code Playgroud)
public class AlternativeAPI3 {
public static void test(String string) {
throw new RuntimeException("Don't call this");
}
public static void test(Integer args) {
System.out.println("OK");
}
}
Run Code Online (Sandbox Code Playgroud)
String为CharSequence(或任何其他"类似类型"):public class AlternativeAPI2 {
public static void test(CharSequence string) {
throw new RuntimeException("Don't call this");
}
public static void test(Integer args) {
System.out.println("OK");
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2054 次 |
| 最近记录: |