或者我是否必须专门枚举我导入的每个类?
我现在正在学习Clojure,在REPL中能够做这样的事情似乎很有用:
(import '(java.io *))
Run Code Online (Sandbox Code Playgroud)
并不是说这是有效的语法,但拥有相同的东西会更好.它可以节省一些打字,特别是在摆弄时.在实际的生产代码中,我总是枚举我正在导入的每个类,无论语言如何,但不必这样做是非常方便的.
我@JvmSynthetic
在kotlin-stdlib中遇到了注释,我想知道它是什么,但不幸的是,它没有记录.
据我所知,将它应用于程序元素会将synthetic
修饰符添加到相应的字节码元素.结果,该元素从Java变得不可见:
class MyClass {
@JvmSynthetic
fun f() { }
}
Run Code Online (Sandbox Code Playgroud)
Java代码中的某处:
MyClass c = new MyClass();
c.f() // Error: cannot resolve method f()
Run Code Online (Sandbox Code Playgroud)
但是在Kotlin代码中仍然可以看到相同的元素:
val c = MyClass()
c.f() // OK
Run Code Online (Sandbox Code Playgroud)
隐藏来自非Kotlin来源的声明是否有效使用@JvmSynthetic
?它是预期用途吗?其他适当的用例是什么?
由于@JvmSynthetic
隐藏了来自Java的函数,它们也无法在Java中被覆盖(当涉及abstract
成员时,调用会产生AbstractMethodError
).鉴于此,我可以@JvmSynthetic
用来禁止在Java源代码中覆盖Kotlin类的成员吗?
我有一个包含一堆静态*lib
文件的库,我希望从JNA
(一个允许从JAVA代码动态调用`dll的Java库)中访问它们,那么有没有办法神奇地将静态库更改为dll?
代码是使用Visual Studio编译的(希望是相关的),我也有适当的头文件.
我无法访问源代码,我也想使用免费(如啤酒)工具.
出于与Java的互操作性的目的,我需要一个具有执行初始化的nullary构造函数的类.这个类的对象需要有类似可变java字段的东西(即,对象代表游戏的后端,并且需要保持游戏状态).
deftype做我想做的一切,除了提供一个无效的构造函数(因为我正在创建一个带字段的类).
我不需要这些字段是公开可读的,所以我可以想到4个解决方案:
使用gen-class; 如果我能避免,我不想这样做.
以某种方式编码私有成员变量以外的deftype知识; 我被告知无法做到这一点.
编写一个修改过的deftype,它也创建了一个nullary构造函数; 坦率地说,我不太了解这种情况.
取deftype创建的类,并以某种方式添加一个新的构造函数.
最后,我需要一个Java类,因为我将把它交给Java代码,它将从类中创建一个新对象.
除了使用gen-class之外,我建议的任何解决方案(或任何我没有想过的解决方案)都可行吗?
use java::util::zip::CRC32:from<java>;
my $crc = CRC32.new();
for 'Hello, Java'.encode('utf-8') {
$crc.'method/update/(B)V'($_);
}
say $crc.getValue();
Run Code Online (Sandbox Code Playgroud)
遗憾的是,这不起作用
Method 'method/update/(B)V' not found for invocant of class 'java.util.zip.CRC32'
Run Code Online (Sandbox Code Playgroud)
此代码可从以下链接获得.这是我能找到的唯一例子
在:constructors map和后续-init定义中,我如何表示一个varargs构造函数(假设超类有多个构造函数,其中一个是varargs)?
我试图用Clojure绑定包装Java库.Java库中的一个特定类定义了一堆静态最终常量,例如:
class Foo {
public static final int BAR = 0;
public static final int SOME_CONSTANT = 1;
...
}
Run Code Online (Sandbox Code Playgroud)
我有一个想法,我可以检查类并将这些常量拉入我的Clojure命名空间,而不是明确地指出def
每一个.
例如,而不是像这样明确地连接它:
(def foo-bar Foo/BAR)
(def foo-some-constant Foo/SOME_CONSTANT)
Run Code Online (Sandbox Code Playgroud)
当模块加载时,我将能够检查Foo
类并动态连接foo-bar
并foo-some-constant
在我的Clojure命名空间中.
我认为这样做有两个原因:
A)在将新常量添加到Foo
类中时自动引入新常量.换句话说,在Java接口添加新常量的情况下,我不必修改我的Clojure包装器.
B)我可以保证常量遵循更多Clojure-esque命名约定
我并没有真的卖掉这个,但是要求扩展我对Clojure/Java互操作的知识似乎是个好问题.
谢谢
我正在尝试使用deftype(来自流行的clojure 1.2分支)来创建一个实现java Servlet接口的java类.我希望下面的代码能够编译(即使它不是很有用).
(ns foo [:import [javax.servlet Servlet ServletRequest ServletResponse]])
(deftype servlet []
javax.servlet.Servlet
(service [this
#^javax.servlet.ServletRequest request
#^javax.servlet.ServletResponse response]
nil))
Run Code Online (Sandbox Code Playgroud)
但它没有编译.编译器生成消息:
Mismatched return type: service, expected: void, had: java.lang.Object
[Thrown class java.lang.IllegalArgumentException]
Run Code Online (Sandbox Code Playgroud)
这对我来说没有意义,因为我回来了.因此,方法的返回类型无效的事实应该不是问题.例如,对于java.util.Set接口:
(deftype bar [#^Number n] java.util.Set (clear [this] nil))
Run Code Online (Sandbox Code Playgroud)
编译没有问题.
那么我对Servlet接口做错了什么?
要明确:我知道典型的情况是将一个servlet抽象类子类化,而不是直接实现这个接口,但是仍然可以这样做.
堆栈跟踪:
(deftype servlet ...的堆栈跟踪是:
Mismatched return type: service, expected: void, had: java.lang.Object
[Thrown class java.lang.IllegalArgumentException]
Restarts:
0: [ABORT] Return to SLIME's top level.
Backtrace:
0: clojure.lang.Compiler$NewInstanceMethod.parse(Compiler.java:6461)
1: clojure.lang.Compiler$NewInstanceExpr.build(Compiler.java:6119)
2: clojure.lang.Compiler$NewInstanceExpr$DeftypeParser.parse(Compiler.java:6003)
3: clojure.lang.Compiler.analyzeSeq(Compiler.java:5289)
4: clojure.lang.Compiler.analyze(Compiler.java:5110)
5: …
Run Code Online (Sandbox Code Playgroud) 以下声明在Kotlin中是合法的.
fun foo(): String = "foo_1"
fun <T> foo(): T = "foo_2" as T
Run Code Online (Sandbox Code Playgroud)
作为字节码我们得到:
public final static foo()Ljava/lang/String;
// signature <T:Ljava/lang/Object;>()TT;
// declaration: T foo<T>()
public final static foo()Ljava/lang/Object;
Run Code Online (Sandbox Code Playgroud)
也可以从Kotlin调用这两种方法.
当我试图从Java中调用其中任何一个时,问题出现了:
ClassKt.foo()
Run Code Online (Sandbox Code Playgroud)
暧昧的电话.两种方法都匹配......
如何避免这样的问题?如何处理这样的方法?如果第三方kt库有同样的问题怎么办?
上面的例子是合成的例子.
我想使用反射从Clojure获取Java对象的方法.其中一个参数类型是Java原语,我不知道如何从Clojure中引用它们.
例如,说我想得到String.valueOf(boolean)
.我最接近的猜测是做
(.getDeclaredMethod String "valueOf" (into-array [Boolean]))
Run Code Online (Sandbox Code Playgroud)
但这失败了,因为Boolean
它不是原始类型本身,而是盒装版本.我试过了boolean
,但是这是指内置的Clojure函数,并且bool
是未定义的.
如何在Clojure中引用原始Java类型?