In Clojure how can I read a public member variables of an instance of a Java class?
In Clojure how can I read a public member variables of an inst开发者_JAVA技巧ance of a Java class? I want something like:
(. instance publicMemberName)
I also tried:
instance/publicMemberName
but this only works with static methods
In Java, the class java.awt.Point
has public fields x
and y
. See the javadocs here http://download.oracle.com/javase/6/docs/api/java/awt/Point.html.
In Clojure the dot macro works for fields and methods. This worked for me:
user=> (let [p (new java.awt.Point 2 4)] (.x p))
2
EDIT: The following also works (note the space between the dot and the p):
user=> (let [p (new java.awt.Point 2 4)] (. p x))
2
EDIT: I decided to make a complete example given that java.awt.Point
has methods getX
and getY
in addition to public fields x
and y
. So here goes. First make a Java class like this:
public class C {
public int x = 100;
}
Compile it
$ javac C.java
Now move C.class
into your clojure directory. Next start the REPL, import the class, and watch it work:
$ java -cp clojure.jar clojure.main
Clojure 1.2.0
user=> (import C)
C
user=> (let [q (new C)] (. q x))
100
Note the other way works too:
user=> (let [q (new C)] (.x q))
100
If your object follows Java bean convention of getFoo
to access member field foo
, and you only need read access (i.e. aren't going to be mutating your object), you can use bean
. That'll give you an immutable Clojure map that mimics the object, and then you can use standard keyword accessors.
user> (bean (java.awt.Point. 1.0 2.0))
{:y 2.0, :x 1.0, :location #<Point java.awt.Point[x=1,y=2]>, :class java.awt.Point}
user> (:x *1)
1.0
精彩评论