如何通过 Clojure 互操作访问静态内部 Java 类?

2022-08-31 16:54:10

基本上我需要做的是这个

FileChannel.MapMode.READ_ONLY

我尝试做显而易见的事情

(.. FileChannel MapMode READ_ONLY)

但这最终会引发异常

java.lang.NoSuchFieldException: MapMode

甚至在互操作文档中为访问静态字段指定的表示法也会产生相同的异常/

(. (FileChannel/MapMode) READ_ONLY)

答案 1

您可以使用 $ 访问内部类

java.nio.channels.FileChannel$MapMode/READ_ONLY

请注意,如果要导入,则还应导入 。FileChannelFileChannel$MapMode


答案 2

语法是一种简化,仅适用于静态字段和方法(对于字段,您甚至可以省略括号)!和 窗体也用于字段/方法,但不适用于嵌套/内部类!(FileChannel/MapMode)...

对于 JVM,内部类只是一个名为的类(编译器为此创建一个文件)。Java 编译器允许您通过 引用它。还可以定义一个名为 的非内部类,编译器允许您将其称为 。但是,您不能同时定义两者,因为两者都具有 的类名(和名为 的文件,因此这将是重复的类名!Outer.InnerOuter$InnerOuter$Inner.classOuter.InnerOuter$InnerOuter$InnerOuter$Inner.classOuter$Inner.class

当使用反射时 - 例如 with - (通常是为了引入一些动态性),你不能省略导入类的包名,你必须使用带有符号的真实类名而不是点。Class.forName()$

可能是因为它的动态性质,Clojure采用了相同的方法,所以如果类在中,你需要使用这个形式 - 即使你已经导入了外部类!为了避免包名称,您可以显式导入内部类,然后将其引用为(其真实类名!),但您不会通过仅导入它来将其简化为:my.package.Outer$Innermy.packagemy.package.Outer$InnerOuter$InnerInner

Inner对JVM没有任何意义,只是Java编译器为您提供了编译时上下文的快捷方式(JVM和方法在运行时不可用!) ...好吧,在Clojure中,当然,你总是可以定义:...或或什么...如果你更喜欢这样。Class.forName(def Inner Outer$Inner)(def Tom Outer$Inner)(def Harry Outer$Inner)


推荐