Como acessar a class Java interna estática via interoperabilidade Clojure?

Basicamente o que eu preciso fazer é isso

FileChannel.MapMode.READ_ONLY 

Eu tentei fazer o óbvio

 (.. FileChannel MapMode READ_ONLY) 

mas isso acaba jogando uma exceção

 java.lang.NoSuchFieldException: MapMode 

até mesmo a / notação especificada para campos estáticos de access na documentação de interoperabilidade produz a mesma exceção

 (. (FileChannel/MapMode) READ_ONLY) 

Você acessa classs internas com $

 java.nio.channels.FileChannel$MapMode/READ_ONLY 

A syntax (FileChannel/MapMode) é uma simplificação e destina-se apenas a campos e methods estáticos (para campos, você pode até mesmo omitir os parênteses)! Também o . e .. formulários são para campos / methods, mas NÃO para classs aninhadas / internas!

Para a JVM, uma class interna Outer.Inner é apenas uma class chamada Outer$Inner (e o compilador cria um arquivo Outer$Inner.class para isso). O compilador Java permite que você se refira a ele pelo Outer.Inner . Você também pode definir uma class não interna denominada Outer$Inner à qual o compilador permite que você se referir como Outer$Inner . Você não pode definir os dois ao mesmo tempo, já que ambos teriam nomes de classs de Outer$Inner (e arquivos .class chamados Outer$Inner.class , então isso seria um nome de class duplicado!)

Ao usar reflection – por exemplo, com Class.forName() – (geralmente para introduzir alguma dinâmica) você não pode omitir o nome do pacote de uma class importada e você deve usar o nome da class real com o sinal $ vez de um ponto.

Provavelmente por sua natureza dinâmica, o Clojure usa a mesma abordagem, então você precisa usar o formulário my.package.Outer$Inner se a class estiver em my.package – mesmo se você já importou a class externa! Para evitar o nome do pacote, você pode importar explicitamente a class interna my.package.Outer$Inner e então se referir a ela como Outer$Inner (seu nome de class real!), Mas você não reduzirá isso para Inner apenas importando:

Inner não tem significado para a JVM, apenas o Java-Compiler oferece este atalho a partir do contexto de tempo de compilation (que não está disponível para a JVM e methods como Class.forName em tempo de execução!) … OK, em Clojure você poderia, é claro, sempre defina: (def Inner Outer$Inner) … ou (def Tom Outer$Inner) ou (def Harry Outer$Inner) ou o que for … se você gosta disso melhor.

    Intereting Posts