I am a software engineer at Google on the Android project and the creator of the Java testing framework TestNG. When I'm not updating this weblog with various software-related posts or speaking at conferences, I am busy snowboarding, playing squash, tennis, golf or volleyball or scuba diving. Cedric is a DZone MVB and is not an employee of DZone and has posted 90 posts at DZone. You can read more from them at their website. View Full User Profile

Accessing the class object in a static context

07.18.2011
| 5893 views |
  • submit to reddit

I often need to access the current class, for example for logging purposes:

public class Foo {
  private Logger logger = LoggerFactory.getLogger(getClass());
}

However, this won’t work in a static context, since you don’t have any this object to call getClass() on:

public class Foo {
  static private Logger logger = LoggerFactory.getLogger(Foo.class);
}

It’s always bothered me to have to copy/paste this line and then remember to replace the name of the class, so here is one way to make this snippet more generic:

public class ClassUtil extends SecurityManager {
 
  public static Class getCurrentClass() {
    return getClassContext()[1];
  }
 
}

Which you use as follows:

public class Foo {
  private static Logger logger = LoggerFactory.getLogger(
      new ClassUtil().getCurrentClass());
}

A somewhat less hacky and cheaper approach is to instantiate an anonymous class in order to materialize a this object:

private static Class thisClass =
    new Object() { }.getClass().getEnclosingClass();
private static Logger logger = LoggerFactory.getLogger(thisClass);

Can you think of any other way?

From http://beust.com/weblog/2011/07/15/accessing-the-class-object-in-a-static-context

Published at DZone with permission of Cedric Beust, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Christopher Brown replied on Tue, 2011/07/19 - 1:40am

Hello Cedric,

Rémi Forax suggested a good Java SE 7 solution:
JSR 292 Goodness: How to get the current class in Java ?

Something like this:

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

--
Christopher

Alexander Wagner replied on Tue, 2011/07/19 - 2:09am

The way to do it in Java 7 is really nice, may I will switch but currently Java 7 is not in scope. So I still will use for this task an Eclipse Java-Editor-Template:

private static Logger logger = LoggerFactory.getLogger(${enclosing_type}.class);

Type "logger" or which keyword u like in a java class and use the content assist (Ctrl + Space) to fullfit it.

regards qpid

 

Collin Fagan replied on Tue, 2011/07/19 - 8:06am

Better? I don't know if this is better or worse. All of thease feel like a hack.

 public static Logger loggerForCurrentClass() {       
        StackTraceElement[] stack = Thread.currentThread().getStackTrace();
        String name = stack[2].getClassName();
        return LoggerFactory.getLogger(name);
} 

Guillaume Jeudy replied on Tue, 2011/07/19 - 12:32pm in response to: Collin Fagan

Hi Collin,

 I don't know the cost of Cedric's approaches but I know generating a stacktrace is expensive so I would avoid this if possible. Perhaps that cost isn't so bad since it's only called once per class that have a static logger.

Cheers,

Guillaume

Neal Johnson replied on Tue, 2011/07/19 - 3:18pm

Hello Cedric

Probable the biggest pain with the static context is when dealing with Loggers as you stated, the method I prefer for most larger projects (where a one extra dependency is not that big an issue) is Project Lombok (http://projectlombok.org/features/index.html).

It allows you to annotate a class with @Log and it takes care of not just the class reference but also the whole private static final Logger logger = ... it covers all the major logging frameworks.

The disadvantages are that its another dependency, it requires Java 6 as a minimum and your IDE may report spurious errors at times. It should be noted that the dependency issue can be removed by the use of delombok.

Qinxian Xiang replied on Wed, 2011/07/20 - 9:38am

I use sun.reflect.Reflection.getCallerClass in a CallerProvider interface implementation, which can be implemented by exception stack as well.

Indeed, I think, it's problem of  Log utils, the Log utils should not add the Logger member.

I just just use qian.geng.log.Log, which  just static methods.

void method1(){

Log.debug(message...);//use the fqcn

Log.debug("main", message ...) ; //use the given logger name

} 

Sirikant Noori replied on Fri, 2012/03/30 - 1:20pm

Another option:

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

You can also grab a stacktrace, though this wouldn’t be my preferred approach:

Thread.currentThread().getStackTrace()[1].getClassName();

Java Exam

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.