Access to nested static classes

568 views
Skip to first unread message

Mark Tomko

unread,
Dec 28, 2009, 5:32:48 PM12/28/09
to Clojure
Is there a way to reference nested static members of Java classes
using Clojure? I tried a few things and couldn't get it to work. To
simplify the question a bit, I wrote the following Java class:

package org.tomko.konkordans;

public class NestedStatics {
public static String FOO = "foo";
public static class LevelOne {
public static enum LevelTwo {
YES,NO;
}
}
}

Then, at the REPL:

user=> (str org.tomko.konkordans.NestedStatics/FOO)
"foo"
user=> (str.org.tomko.konkordans.NestedStatics/LevelOne)
java.lang.ClassNotFoundException:
str.org.tomko.konkordans.NestedStatics (NO_SOURCE_FILE:0)
user=>

So, it's clear that I have the NestedStatics class in my classpath,
and that I can reference static members that are of a fundamental data
type. But attempting to reach in one level deeper does not succeed.

I also tried importing LevelOne into my namespace using a :use, but
that didn't work - although I'm a bit hazy on the precise syntax for
that so it might be my fault. A search in this forum didn't turn up
anything quite like this, but there was some discussion about import
statics that might be relevant.

David Brown

unread,
Dec 28, 2009, 5:42:39 PM12/28/09
to clo...@googlegroups.com
On Mon, Dec 28, 2009 at 02:32:48PM -0800, Mark Tomko wrote:

>user=> (str.org.tomko.konkordans.NestedStatics/LevelOne)

Does

str.org.tomko.konkordans.NestedStatics$LevelOne/ONE

Work?

You can always look in the class output directory that the Java
compiler generates, and see the resulting class name that it creates
(just change the slashes in the path into dots).

David

Mark Tomko

unread,
Dec 28, 2009, 5:48:41 PM12/28/09
to Clojure
This appears to work:

user=> (str org.tomko.konkordans.NestedStatics$LevelOne)
"class org.tomko.konkordans.NestedStatics$LevelOne"

Is this depending on a detail of implementation? It feels funny to
me, but perhaps it's the best way to do it.

Mark Tomko

unread,
Dec 28, 2009, 5:50:59 PM12/28/09
to Clojure
This, however, does not work:

(ns org.tomko.konkordans.analysis
(:import
(org.tomko.konkordans NestedStatics)))

(def foo NestedStatics$LevelOne$LevelTwo/NO)

user=> (load-file "/Users/mark/IdeaProjects/Konkordans/src/org/tomko/
konkordans/analysis.clj")
java.lang.Exception: No such namespace: NestedStatics$LevelOne
$LevelTwo (analysis.clj:5)

David Brown

unread,
Dec 28, 2009, 11:09:02 PM12/28/09
to clo...@googlegroups.com
On Mon, Dec 28, 2009 at 02:50:59PM -0800, Mark Tomko wrote:
>This, however, does not work:
>
>(ns org.tomko.konkordans.analysis
> (:import
> (org.tomko.konkordans NestedStatics)))
>
>(def foo NestedStatics$LevelOne$LevelTwo/NO)

The class is called NestedStatics$LevelOne$LevelTwo, so you would have
to import that if you wanted to use it. As far as the JVM is
concerned, NestedStatics, NestedStatics$LevelOne and
NestedStatics$LevelOne$LevelTwo are just three independent classes.

Java added nested classes, but didn't really add them to the JVM. It
just makes longer class names using the '$'.

It's probably safe to rely on this behavior, since there is plenty of
code that depends upon it working this way.

David

Mark Tomko

unread,
Dec 29, 2009, 8:46:10 AM12/29/09
to Clojure
That's fair, except that it's a little disappointing that I can't
reference nested structures from Clojure in the natural way, akin to
Java. In Java, if I had imported NestedStatics, I could reference
NestedStatics.LevelOne without bringing LevelOne into my namespace
(and possibly into conflict with other imports!). In Clojure,
however, it appears that any class that I want to reference needs to
be fully qualified or explicitly imported into my own namespace.
Reply all
Reply to author
Forward
0 new messages