web-dev-qa-db-ja.com

Clojure相互運用機能を介して静的内部Javaクラスにアクセスする方法は?

基本的に私がする必要があるのはこれです

FileChannel.MapMode.READ_ONLY

当たり前のことをやってみました

(.. FileChannel MapMode READ_ONLY)

しかし、それは例外をスローすることになります

Java.lang.NoSuchFieldException: MapMode

/相互運用ドキュメント のアクセス静的フィールドとして指定された表記は、同じ例外を生成します

(. (FileChannel/MapMode) READ_ONLY)
55
Jakub Arnold

$で内部クラスにアクセスします

Java.nio.channels.FileChannel$MapMode/READ_ONLY
84
Hamza Yerlikaya

構文_(FileChannel/MapMode)_は単純化されたものであり、静的フィールドとメソッドのみを対象としています(フィールドの場合、括弧を省略してもかまいません)。また、_._および_.._フォームはフィールド/メソッド用ですが、ネストされた/内部クラス用ではありません!

JVMの場合、内部クラス_Outer.Inner_は_Outer$Inner_という名前のクラスです(コンパイラーはこのためにファイル_Outer$Inner.class_を作成します)。 Javaコンパイラーでは_Outer.Inner_で参照できます。コンパイラーで_Outer$InnerOuter$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コンパイラだけがコンパイル時のコンテキストからこのショートカットを提供します(これはJVMや実行時に_Class.forName_のようなメソッドでは利用できません!)...もちろん、Clojureでは、常に次のように定義できます。_(def Inner Outer$Inner)_ ...または_(def Tom Outer$Inner)_または_(def Harry Outer$Inner)_またはその他...必要に応じて。

15
Martin Valjavec