如何通过Clojure interop访问静态内部Java类?
基本上我需要做的是这个
FileChannel.MapMode.READ_ONLY
我试图做明显的
(.. FileChannel MapMode READ_ONLY)
但最终抛出exception
java.lang.NoSuchFieldException: MapMode
甚至在interop文档中为访问静态字段指定的/
notation也会产生相同的exception
(. (FileChannel/MapMode) READ_ONLY)
你用$来访问内部类
java.nio.channels.FileChannel$MapMode/READ_ONLY
语法(FileChannel/MapMode)
是一种简化,仅用于静态字段和方法(对于字段,甚至可以省略括号)! 也是.
和..
表单是为字段/方法,但不适用于嵌套/内部类!
对于JVM,内部类Outer.Inner
只是一个名为Outer$Inner
的类(编译器为此创build一个文件Outer$Inner.class
)。 Java编译器让你通过Outer.Inner
来引用它。 您还可以定义一个名为Outer$Inner
非内部类,让编译器将其引用为Outer$Inner
。 然而,你不能同时定义两者,因为两者的类名都是Outer$Inner
(和名为Outer$Inner.class
.class
文件,所以这将是一个重复的类名!)
当使用reflection – 例如Class.forName()
– (通常引入一些dynamic性)时,您不能省略导入的类的包名称,您必须使用带$
符号的实际类名称而不是点。
可能是因为它的dynamic特性,Clojure采用了相同的方法,所以如果类在my.package
,即使已经导入了外部类,也需要使用my.package.Outer$Inner
forms! 为了避免包名,你可以显式地导入内部类my.package.Outer$Inner
,然后将其引用为Outer$Inner
(它的真实类名!),但是不会将其仅仅导入到Inner
:
Inner
对JVM没有任何意义,只是Java编译器为您提供了编译时上下文的快捷方式(在运行时JVM和类似于Class.forName
方法是不可用的)…在Clojure中,您可以,当然,总是定义: (def Inner Outer$Inner)
…或(def Tom Outer$Inner)
或(def Harry Outer$Inner)
或者其他…如果你更喜欢那个。