Basically what I need to do is this
FileChannel.MapMode.READ_ONLY
I tried doing the obvious
(.. FileChannel MapMode READ_ONLY)
but that ends up throwing an exception
java.lang.NoSuchFieldException: MapMode
even the /
notation specified as for access static fields in the interop documentation produces the same exception
(. (FileChannel/MapMode) READ_ONLY)
And like static class methods, a static nested class cannot refer directly to instance variables or methods defined in its enclosing class: it can use them only through an object reference. They are accessed using the enclosing class name. To instantiate an inner class, you must first instantiate the outer class.
Non-static nested classes are called inner classes. Nested classes that are declared static are called static nested classes. A nested class is a member of its enclosing class. Non-static nested classes (inner classes) have access to other members of the enclosing class, even if they are declared private.
Overview. Clojure was designed to be a hosted language that directly interoperates with its host platform (JVM, CLR and so on). Clojure code is compiled to JVM bytecode. For method calls on Java objects, Clojure compiler will try to emit the same bytecode javac would produce.
You just need to write a class within a class. Unlike a class, an inner class can be private and once you declare an inner class private, it cannot be accessed from an object outside the class. Following is the program to create an inner class and access it.
You access inner classes with $
java.nio.channels.FileChannel$MapMode/READ_ONLY
Mind that if you are importing FileChannel
you should also import FileChannel$MapMode
.
The syntax (FileChannel/MapMode)
is a simplification and intended only for static fields and methods (for fields, you may even omit the parentheses)! Also the .
and ..
forms are for fields/methods but NOT for nested/inner classes!
For the JVM, an inner class Outer.Inner
is just a class named Outer$Inner
(and the compiler creates a file Outer$Inner.class
for this). The Java compiler lets you refer to it by Outer.Inner
. You can also define a not-inner class named Outer$Inner
to which the compiler lets you refer as Outer$Inner
. You cannot define both at the same time, however, since both would have class names of Outer$Inner
(and .class
files named Outer$Inner.class
, so this would be a duplicate class name!)
When using reflection - e.g. with Class.forName()
- (usually to introduce some dynamicity) you cannot omit the package name of an imported class and you must use the real class name with the $
sign instead of a dot.
Probably for its dynamic nature, Clojure takes the same approach, so you need to use the form my.package.Outer$Inner
if the class is in my.package
- even if you imported the outer class already! To avoid the package name, you can explicitly import the inner class my.package.Outer$Inner
and then refer to it as Outer$Inner
(its real class name!) but you will not reduce this to Inner
by just importing it:
Inner
has no meaning to the JVM, just the Java-Compiler offers you this shortcut from the compile time context (which is NOT available to the JVM and methods like Class.forName
at runtime!) ... OK, in Clojure you could, of course, always define: (def Inner Outer$Inner)
... or (def Tom Outer$Inner)
or (def Harry Outer$Inner)
or whatever ... if you like that better.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With