Skip to main content

JSR 292 Goodness: How to get the current class in Java ?

Posted by forax on October 26, 2010 at 6:14 AM PDT

This a question that is often asked by my students:
How to get the current class in Java  ?

In the code below, instead of A.class, I want to something like "get the current class".
One of my student even invent a new syntax for that purpose this.class.
But guess what, the compiler doesn't like invented syntaxes.

  public class A {
    public static void main(String[] args) {
       System.out.println("current class " + A.class);
    }
  }

My standard answer was that there is no obvious way to do that.
In fact, there is a hacky way to get the current class using exception, stack trace element and Class.forName.
The way to combine those elements is left as an exercice to the reader.

This is no more true with JDK 7 which will include the JSR 292 API (java.dyn) .
This API provides, as a side effect, a way  to get the current class.

  import java.dyn.MethodHandles;
   
  public class A {
    public static void main(String[] args) {
       System.out.println(MethodHandles.lookup().lookupClass());
    }
  }

MethodHandles.lookup() returns a Lookup object which is a factory of method handles.
The Lookup object embodies the class of the code that calls the method lookup().
This class will be used to check if the code has the right or not to create a method handle.
And You can retreive this class using the method lookupClass().

See you soon for tips and tricks on JDK 7/JSR 292.

cheers,
Rémi

Related Topics >>

Comments

<p>&nbsp;This is great, but if I have implemented an ...

This is great, but if I have implemented an abstract class, this method lookup() returns the name of the superclass.

There's a way to know the current class?

<span class="Apple-tab-span" style="white-space:pre"> </span>public static &lt;T extends Entity&gt; T find(Long id) throws Exception {
   Session session = HibernateUtil.getSessionFactory().getCurrentSession();
   Transaction transaction = session.beginTransaction();
   // NOPE returns Entity
   // Class klass = Thread.currentThread().getContextClassLoader().loadClass(Thread.currentThread().getStackTrace()[1].getClassName());
   // NOPE returns Entity
   // Class klass = Class.forName(Thread.currentThread().getStackTrace()[0].getClassName());
   // NOPE returns Entity
   Class klass = MethodHandles.lookup().lookupClass());
   T object = (T) session.load(klass, id);
   return object;
}

<p>I don't think you can do that because a static method is ...

I don't think you can do that because a static method is attached
to its declaring class. So the whole concept of current class is mooted.

Rémi

<p>&nbsp;Ok, so build a simple find method similar to ...

Ok, so build a simple find method similar to ActiveRecord is impossible even in jdk7? C'mon...

How to get the current class

You can use this functionality currently on OpenJDK 7, but you need to pass some additional arguments on the command line.

java -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles -XX:+EnableInvokeDynamic A

The last argument on enabling InvokeDynamic is to avoid a warning.

new

new Object(){}.getClass().getEnclosingClass()

Nice.

Nice.

Well, if you're not in a

Well, if you're not in a static context, there is always

this.getClass()

.. and the hacky way for a static context:
Thread.currentThread().getContextClassLoader().loadClass(Thread.currentThread().getStackTrace()[1].getClassName())

or
Class.forName(Thread.currentThread().getStackTrace()[1].getClassName())

but I generally try to avoid using Class.forName

Unless you add some extra

Unless you add some extra restriction (say, the class is final), then you may pick up a subclass instead of the current class with `this.getClass()`. More confusion if the class is not abstract.
Also, the current thread context class loader may not be what you want. Using the current thread context class loader is always a bit of a hack anyway. Single argument `Class.forName` does use the current class(!) (loader). The implementation used by `forName` is exposed through `SecurityManager.getClassContext`, which provides another hacky way to find the current `Class` today.

Yes, be careful when using

Yes, be careful when using Class.forName(...) as you might have problems when using it with OSGi bundles. There are a number of posts around that describe related issues, but I just found a good one by Neil Barlett: http://njbartlett.name/2010/08/30/osgi-readiness-loading-classes.html