2011-08-21 16 views
49

Básicamente lo que tengo que hacer es esta¿Cómo acceder a la clase Java interna estática a través de la interoperabilidad Clojure?

FileChannel.MapMode.READ_ONLY 

He intentado hacer lo obvio

(.. FileChannel MapMode READ_ONLY) 

pero que termina por lanzar una excepción

java.lang.NoSuchFieldException: MapMode 

incluso la notación / especifica como para acceder a los campos estáticos en el interop documentation produce la misma excepción

(. (FileChannel/MapMode) READ_ONLY) 

Respuesta

75

Se accede a las clases internas con $

java.nio.channels.FileChannel$MapMode/READ_ONLY 
+27

No olvide que si está importando FileChannel con la función 'import' o con la palabra clave': import', también debe especificar que está importando 'FileChannel $ MapMode' –

+1

Gracias @TerjeDahl. Creo que deberías editar tu pregunta para incluir esto, Hamza Yerlikaya. – Joe

11

La sintaxis (FileChannel/MapMode) es una simplificación y destinado únicamente para campos y métodos estáticos (por campos, incluso se puede omitir los paréntesis)! Además, los formularios . y .. son para campos/métodos, ¡pero NO para clases internas/anidadas!

Para la JVM, una clase interna Outer.Inner es solo una clase llamada Outer$Inner (y el compilador crea un archivo Outer$Inner.class para esto). El compilador de Java le permite consultarlo por Outer.Inner. También puede definir una clase no interna llamada Outer$Inner a la cual el compilador le permite referirse como Outer$Inner. No se pueden definir dos cosas al mismo tiempo, sin embargo, ya que ambos tendrían nombres de las clases de Outer$Inner (y .class archivos denominados Outer$Inner.class, por lo que este sería un nombre de clase duplicado!)

Cuando se utiliza la reflexión - por ejemplo, con Class.forName() - (generalmente para introducir algo de dinámica) no puede omitir el nombre del paquete de una clase importada y debe usar el nombre de clase real con el signo $ en lugar de un punto.

Probablemente por su naturaleza dinámica, Clojure tiene el mismo enfoque, por lo que debe utilizar el formulario my.package.Outer$Inner si la clase está en my.package, ¡incluso si importó la clase externa ya! Para evitar el nombre del paquete, puede importar de forma explícita la clase interna my.package.Outer$Inner y luego referirse a ella como Outer$Inner (su nombre de clase real!) Pero no se reducirá el número a Inner con sólo importarlo:

Inner tiene ningún significado para JVM, solo el compilador Java le ofrece este acceso directo desde el contexto de compilación (que NO está disponible para la JVM y métodos como Class.forName en tiempo de ejecución) ... Bien, en Clojure, por supuesto, siempre puede definir: (def Inner Outer$Inner) ... o (def Tom Outer$Inner) o (def Harry Outer$Inner) o lo que sea ... si te gusta más.

+0

esta es quizás una buena explicación. Gracias. – tutysara

Cuestiones relacionadas