Подтвердить что ты не робот

Как получить доступ к статическому внутреннему классу Java через Clojure interop?

В основном, что мне нужно сделать, это

FileChannel.MapMode.READ_ONLY

Я попытался сделать очевидный

(.. FileChannel MapMode READ_ONLY)

но в результате возникает исключение

java.lang.NoSuchFieldException: MapMode

даже обозначение /, указанное как для статических полей доступа в документации interop, дает то же исключение

(. (FileChannel/MapMode) READ_ONLY)
4b9b3361

Ответ 1

Доступ к внутренним классам с помощью $

java.nio.channels.FileChannel$MapMode/READ_ONLY

Ответ 2

Синтаксис (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 во время выполнения!)... OK, в Clojure вы, конечно, всегда можете определить: (def Inner Outer$Inner)... или (def Tom Outer$Inner) или (def Harry Outer$Inner) или что-то еще... если вам это нравится.