繁体   English   中英

如何在 Clojure 中调用重载的 Java 方法

[英]How do I call overloaded Java methods in Clojure

对于此示例 Java class:

package foo;
public class TestInterop
{   public String test(int i)
    { return "Test(int)"; }

    public String test(Object i)
    { return "Test(Object)"; }
}

当我启动 Clojure 并尝试调用 test(int) 方法时,却调用了 test(Object) 方法,因为 Clojure 自动将 integer 装箱到 java.lang.Integer object。

如何强制 Clojure 调用 test(int) 方法?

user=> (.test (new foo.TestInterop) 10)
"Test(Object)"

我想在 AWT 中调用类似Component.add(Component comp, int index)的方法,而是继续调用add(Component comp, Object constraints) ,所以工具栏上的按钮总是以错误的顺序出现。

关于Freenode的#clojure频道正在讨论这个话题。 克里斯·豪瑟(谁会发布一个答案,但最终决定他太忙了,不能这样做)发布了一个Gist ,它演示了booleanObject重载方法会发生什么。 事实证明,在某些情况下,除了(boolean ...)强制转换之外,还需要一个类型提示。 讨论非常有启发性,Clojure编译过程中的一些黑暗角落变得非常明亮。 (参见下面的IRC日志链接。)

基本上,如果一个对象是在方法调用形式中创建的 - (.foo (Foo.) ...) ,那么说 - 类型提示不是必需的; 同样没有必要将对象构造为封闭let形式的本地值(请参阅下面的更新2和我的Gist版本)。 但是,如果通过Var查找获得对象,则需要类型提示 - 可以在Var本身上提供,也可以在调用站点上提供用于引用Var的符号。

Gist中的Java代码:

package mypkg;

public class Ugly {
    public Ugly(){}
    public String foo(boolean i) { return "bool: " + i; }
    public String foo(Object o) { return "obj: " + o; }
}

和Clojure代码:

(.foo (mypkg.Ugly.) 5)
;=> "obj: 5"

(.foo (mypkg.Ugly.) true)
;=> "obj: true"

(.foo (mypkg.Ugly.) (boolean true))
;=> "bool: true"


(def u (mypkg.Ugly.))
(.foo u (boolean true))
;=> "obj: true"

(.foo #^mypkg.Ugly u (boolean true))
;=> "bool: true"

注意Clojure编译器如何需要对u进行类型提示才能编译直接方法调用。 否则,似乎会生成基于反射的代码,这显然会忽略这样一个事实,即参数在此过程中应该是一个原始的。

我的补充如下(这是我上面的Gist的分支 )。

;; renamed mypkg.Ugly to foo.TestInterop2 when doing my tests
user> (let [t (foo.TestInterop2.)]
        (.foo t (boolean true)))
"bool: true"

;;; type-hinting the Var
user> (def #^foo.TestInterop2 x (foo.TestInterop2.))
#'user/x
user> (.foo x (boolean true))
"bool: true"

这个话题首先提到了这一点 半小时后 ,Chouser发布了Gist ,之后讨论变得越来越有趣。

user=> (.test (foo.TestInterop.) 10)
"Test(Object)"
user=> (.test (foo.TestInterop.) (int 10))
"Test(int)"

Clojure中的数字通常是盒装的(int => Integer),除非你特别要求原语。

以下是有关Clojure中基元的更多信息。

要调用Container.add(Component child, int index)使用

(.add ^Container container ^Component child ^int index)

或者您可以在前面为ContainerComponent添加类型提示,但int的类型提示必须在对add的调用中。 例如,

(defn add-component [^Container container ^Component component index]
    (.add container component ^int index)

原始类型int不能用作 fn 定义中的类型提示。 我不确定它还可以用在哪里,所以 AFAIK 它必须直接出现在方法调用中,除非使用数字文字,在这种情况下,根据我的经验,不需要类型提示。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM