如何通过Clojure interop访问静态内部Java类?

Jak*_*old 54 java interop clojure

基本上我需要做的就是这个

FileChannel.MapMode.READ_ONLY
Run Code Online (Sandbox Code Playgroud)

我试着做的很明显

(.. FileChannel MapMode READ_ONLY)
Run Code Online (Sandbox Code Playgroud)

但最终会抛出异常

java.lang.NoSuchFieldException: MapMode
Run Code Online (Sandbox Code Playgroud)

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

(. (FileChannel/MapMode) READ_ONLY)
Run Code Online (Sandbox Code Playgroud)

Ham*_*aya 85

您可以使用$访问内部类

java.nio.channels.FileChannel$MapMode/READ_ONLY
Run Code Online (Sandbox Code Playgroud)

  • 不要忘了,如果你是用`import`功能或用`进口FileChannel:import`关键字,你还必须指定要导入`FileChannel $ MapMode` (32认同)

小智 15

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

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

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

可能由于它的动态特性,Clojure采用了相同的方法,因此my.package.Outer$Inner如果类所在,你需要使用表单my.package- 即使你已经导入了外部类!要避免软件包名称,可以显式导入内部类my.package.Outer$Inner,然后将其称为Outer$Inner(它的真实类名!),但不要Inner通过导入它来减少它:

Inner对JVM没有任何意义,只是Java-Compiler在编译时上下文中提供了这个快捷方式(JVM和Class.forName运行时的方法都不可用!)......好的,在Clojure中你当然可以定义:(def Inner Outer$Inner)...或者(def Tom Outer$Inner)或者(def Harry Outer$Inner)等等......如果你更喜欢那样的话.