Getting the Class Name from a Static Method in Java

Getting the class name from a static method in Java

In order to support refactoring correctly (rename class), then you should use either:

 MyClass.class.getName(); // full name with package

or (thanks to @James Van Huis):

 MyClass.class.getSimpleName(); // class name and no more

Java: get the called class name from static method

This is not possible, at least not in the general sense that you've asked.

There is no method B.getName(). While you can type that in code, it will be compiled to identical bytecode to A.getName() (and I think you get a compiler warning too).

Thus at runtime, there is no way to tell how someone referenced the static method - just as there's no way to tell what local variable names a caller is using.

How to call getClass() from a static method in Java?

The Answer

Just use TheClassName.class instead of getClass().

Declaring Loggers

Since this gets so much attention for a specific usecase--to provide an easy way to insert log declarations--I thought I'd add my thoughts on that. Log frameworks often expect the log to be constrained to a certain context, say a fully-qualified class name. So they are not copy-pastable without modification. Suggestions for paste-safe log declarations are provided in other answers, but they have downsides such as inflating bytecode or adding runtime introspection. I don't recommend these. Copy-paste is an editor concern, so an editor solution is most appropriate.

In IntelliJ, I recommend adding a Live Template:

  • Use "log" as the abbreviation
  • Use private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger($CLASS$.class); as the template text.
  • Click Edit Variables and add CLASS using the expression className()
  • Check the boxes to reformat and shorten FQ names.
  • Change the context to Java: declaration.

Now if you type log<tab> it'll automatically expand to

private static final Logger logger = LoggerFactory.getLogger(ClassName.class);

And automatically reformat and optimize the imports for you.

Is it possible to get the class name from a static method?

You can do it by creating (not throwing) a new Exception and inspecting its stack trace. Your class will be the zeroth element as it is the origin of the Exception. It kinda feels wrong, but it will work.

System.out.println( new Exception().getStackTrace()[0].getClassName() );

You can do the same with the Thread class. This seems cleaner to me, but the line is slightly longer. Your class is now the first element in the stacktrace rather than the zeroth. Thread.getStackTrace() is the zeroth.

System.out.println( Thread.currentThread().getStackTrace()[1].getClassName() );

For example, typing MyClass.class.getName() is no more useful than just "Myclass".

On the contrary, if you rename MyClass using your IDE's refactor function it will replace MyClass.class.getName() with RenamedClass.class.getName(). If you put a string in there you'll have to do it manually.

Get class name from static method reference

I'm afraid you can't. The calls to Class1::method, Class2::method are wrapped inside a lambda closure that implements MyFuncInt, which has no methods to access the wrapped class (it's not even a declared field of the lambda class).

I'd say you can't use a functional interface. You'd have to make a functor to which you pass a reference to the class (or just a string with the class name), so you can retrieve it later:

class MyFunctor implements MyFuncInt {

public final Class<?> clazz;
private final MyFuncInt func;

public MyFunctor(Class<?> clazz, MyFuncInt func) {
this.clazz = clazz;
this.func = func;
}

@Override
public void doSomething() {
func.doSomething();
}
}

Then instantiate like:

new MyFunctor(Class1.class, Class1::method);

get caller class name from inherited static method

What you can do, but shouldn't :) is use the Throwable getStackTrace method. Aside from the smell, this is pretty slow, because getting the stack trace isn't that fast. But you will get an array of StackTraceElement, and each one will contain the class of teh class that is calling it (and you can also get the file and line, and if you separate the two with a : you can get a clickable link in eclipse, not that I'd ever do such a thing...).

Something like

String className = new Throwable().getStackTrace()[1].getClassName(); 

Hope that helps :)



Related Topics



Leave a reply



Submit