Accessing object fields

Accessing static fields and properties

The recommmended way to access fields uses the colon notation. For static fields and properties the following is recommended:

class-expression:field-name

For example:

java.lang.Integer:MAX_VALUE

A property with a get method is equivalent to a field. The following are all equivalent:

java.util.Currency:available-currencies
java.util.Currency:availableCurrencies
(java.util.Currency:getAvailableCurrencies)

Just like for a method call, the class-expression can be a class in the current lexical scope, a fully-qualified class name, or more generally an expression that evaluates to a class.

Accessing instance fields and properties

The syntax is:

instance:field-name

The field-name can of course be the name of an actual object field, but it can also be the name of a property with a zero-argument get method. For example, if cal is a java.util-Calendar instance, then the following are all equivalent:

cal:time-zone
cal:timeZone
(cal:getTimeZone)
(cal:get-time-zone)

You can use colon notation to assign to a field:

(set! cal:time-zone TimeZone:default)

which is equivalent to:

(cal:setTimeZone (TimeZone:getDefault))

A Java array only has the length field, plus the class property:

(int[] 4 5 6):length ⇒ 3
(int[] 4 5 6):class:name ⇒ "int[]"

Using field and static-field methods

The following methods are useful in cases where colon notation is ambiguous, for example where there are both fields and methods with the same name. You might also prefer as a matter of style, to emphasise that a field is being accessed.

Procedure: field object fieldname

Get the instance field with the given fieldname from the given Object. Returns the value of the field, which must be accessible. This procedure has a setter, and so can be used as the first operand to set!.

The field name is "mangled" (see Mangling) into a valid Java name. If there is no accessible field whose name is "fieldname", we look for a no-argument method whose name is "getFieldname" (or "isFieldname" for a boolean property).

If object is a primitive Java array, then fieldname can only be 'length, and the result is the number of elements of the array.

Procedure: static-field class fieldname

Get the static field with the given fieldname from the given class. Returns the value of the field, which must be accessible. This procedure has a setter, and so can be used as the first operand to set!.

If the fieldname is the special name class, then it returns the java.lang.Class object corresponding to class (which is usually a gnu.bytecode.ClassType object).

Examples:

(static-field java.lang.System 'err)
;; Copy the car field of b into a.
(set! (field a 'car) (field b 'car))

Procedure: slot-ref object fieldname

A synonym for (field object fieldname).

Procedure: slot-set! object fieldname value

A synonym for (set! (field object fieldname) value).

Older colon-dot notation

There is older syntax where following the colon there is field name a following the colon and a period.

To access an static field named field-name use this syntax

(prefix:.field-name instance)

The prefix can be as discussed in See Method operations. Here are 5 equivalent ways:

(java.lang.Integer:.MAX_VALUE)
(<java.lang.Integer>:.MAX_VALUE)
(define-namespace Int32 <java.lang.Integer>)
(Int32:.MAX_VALUE)
(define-namespace Integer "class:java.lang.Integer")
(Integer:.MAX_VALUE)
(define-alias j.l.Integer java.lang.Integer)
(j.l.Integer:.MAX_VALUE)

You can set a static field using this syntax:

(set! (prefix:.field-name) new-value)

The special field name class can be used to extract the java.lang.Class object for a class-type. For example:

(java.util.Vector:.class) ⇒ class java.util.Vector

To access a instance field named field-name use the following syntax. Note the period before the field-name.

(*:.field-name instance)

This syntax works with set! - to set the field use this syntax:

(set! (*:.field-name instance) new-value)

Here is an example:

(define p (list 3 4 5))
(*:.cdr p) ⇒ (4 5)
(set! (*:.cdr p) (list 6 7))
p ⇒ (3 6 7)

You can specify an explicit class:

(prefix:.field-name instance)

If prefix is bound to <class>, then the above is equivalent to:

(*:.field-name (as <class> instance))