如何通过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$Innerforms! 为了避免包名,你可以显式地导入内部类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)或者其他…如果你更喜欢那个。