Learning Clojure/Calling Java< Learning Clojure
- (. instance method args*)
- (. class method args*)
The special form
. also known as host, invokes a public Java method or retrieves the value of a public Java field:
(. foo bar 7 4) ; call the method bar of the instance/class foo with arguments 7 and 4 (. alice bob) ; return the value of public field bob of the instance/class alice
Notice that accessing a field might be mistaken for invoking a parameter-less method: if a class has a parameter-less method and public field of the same name, the ambiguity is resolved by assuming that calling the method is what's intended.
If the first argument to . is a symbol, the symbol is evaluated specially: if the symbol resolves to a Class referred in the current namespace, then this is a call to one of that Class's static methods; otherwise, this is a call to a method of the instance resolved from the symbol. So confusingly, using . with a non-referred symbol resolving to a Class is an invocation of a method of that Class object, not an invocation of a static method of the class represented by that Class object:
(. String valueOf \c) ; invoke the static method String.valueOf(char) with argument 'c' (def ned String) ; interned Var mapped to ned now holds the Class of String (. ned valueOf \c) ; exception: attempt to call Class.valueOf, which doesn't exist
While the . operator is the generic operator for accessing java, there are more readable reader macros that should be preferred instead of using . directly:
- (.field instance args*)
- Class/StaticField or (Class/StaticMethod args*)
Note: Prior to Subversion revision 1158, .field was also usable for static access. However, in recent versions of Clojure, a (.field ClassName) form is treated as if ClassName were the corresponding instance of class java.lang.Class.
Thus, the above examples would be written as:
(String/valueOf \c) ; Static method access! (def ned String) (.valueOf ned \c) ; This will fail (.valueOf String \c) ; And in recent versions, so will this.
If there is need to manipulate the Class object, for example to call the Class.newInstance method, one can do the following:
(. (identity String) newInstance "fred") ; will create a new instance; this will work in all versions of clojure (.newInstance String "fred") ; will work only in a recent enough version of clojure. Expands to the above form. (.newInstance (identity String) "fred") ; this was required in old versions
- (new class args*)
The special form
new instantiates a Java class, calling its constructor with the supplied arguments:
(new Integer 3) ; instantiate Integer, passing 3 as argument to the constructor
Like with calling static methods with ., the class must be specified as a symbol, not as the Class object of the class you wish to instantiate:
(new String "yo") ; new String("yo") (def ned String) ; interned Var mapped to ned now holds the Class of String (new ned "yo") ; exception: new Class("yo") is invalid
A reader macro exists for new as well:
- (Classname. args*)
(String. "yo") ; equivalent to (new String "yo"). Notice the dot!