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.
how to solve cannot make a static reference to the non-static method?
(If your class name is Main
then) use Main.class.getResource
instead of this.getClass.getResource
Read this for more details.
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
I can't access my class location from static method
Instead of using getClass()
you can use FileWriting.class
.
The non-static method getClass()
can't be called from the static main method unless you have an instance of the class. You can however get the class in the static context as shown above.
How to get getclass().getResource() from a static context?
It can't compile because getResource
takes a resource name (a String
, and not a File
) as parameter, in order to load a resource using the class loading mechanism (from the classpath). Using it with a File
makes no sense. If you want to open a file, just use a FileInputStream
or a FileReader
.
See http://docs.oracle.com/javase/6/docs/api/java/lang/ClassLoader.html#getResource%28java.lang.String%29, and include the compiler error message next time you have such a question.
How to get class which invokes static method?
At first, I thought this is impossible as the java compiler can figure out which method will be called and emit the same instruction.
Turns out that it actually records the way the class is called.
So, the question now becomes:
- How do we get the place where the method is called?
- How do we use this information to get the way the method is called?
The first one is easy: We use a StackWalker, which can give us the bytecode index.
Now we only need to parse the class, look at the instruction at that bytecode index, and figure out how this method was called.
I used ASM for that, but it might be the wrong tool here.
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.lang.StackWalker.StackFrame;
import java.util.Set;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import static org.objectweb.asm.Opcodes.*;
class CallingClassVisitor extends ClassVisitor {
private final StackFrame where;
String ownerClass = null;
public CallingClassVisitor(StackFrame where) {
// We need a backing ClassWriter, so the Label is resolved.
super(ASM8, new ClassWriter(0));
this.where = where;
}
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature,
String[] exceptions) {
MethodVisitor parent = super.visitMethod(access, name, descriptor, signature, exceptions);
if (name.equals(where.getMethodName()) && descriptor.equals(where.getDescriptor())) {
return new CallingMethodVisitor(where, parent);
} else {
return parent;
}
}
class CallingMethodVisitor extends MethodVisitor {
private final StackFrame where;
public CallingMethodVisitor(StackFrame where, MethodVisitor parent) {
super(ASM8, parent);
this.where = where;
}
@Override
public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) {
Label lbl = new Label();
visitLabel(lbl);
if (lbl.getOffset() == where.getByteCodeIndex()) {
ownerClass = owner;
}
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
}
}
public String getOwnerClass() {
return ownerClass;
}
}
class A {
static final StackWalker SW = StackWalker.getInstance(Set.of(StackWalker.Option.RETAIN_CLASS_REFERENCE));
public static void doIt() {
StackFrame sf = SW.walk(s -> s.skip(1).findFirst()).orElseThrow();
InputStream source = sf.getDeclaringClass().getClassLoader()
.getResourceAsStream(sf.getClassName().replace('.', '/') + ".class");
try {
CallingClassVisitor ccv = new CallingClassVisitor(sf);
new ClassReader(source).accept(ccv, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
String how = ccv.getOwnerClass();
System.out.println(how);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}
class B extends A { }
public class NewMain {
public static void main(String[] args) {
A.doIt();
B.doIt();
}
}
In the end, I'm not sure if your requirement is worth that effort.
Why isn't getClass() available as a static method?
If nothing else, because it isn't legal to have both a static
and non-static
version of a method (probably because it's legal, if discouraged, to call a static
method in a non-static
context).
I also feel like such a method, while useful in the context of defining a logger or whatever, could be confusing in other contexts, such as when called from an instance method.
Related Topics
Difference Between Java.Exe and Javaw.Exe
How to Do Union, Intersect, Difference and Reverse Data in Java
Barcode Scanner Implementation on Java
How to Manage Exceptions Thrown in Filters in Spring
Java 8 Stream's .Min() and .Max(): Why Does This Compile
How to Build Sources Jar with Gradle
Scala Equivalent of Java Java.Lang.Class<T> Object
How to Create a Sub Array from Another Array in Java
Generic Type Parameter Naming Convention for Java (With Multiple Chars)
Java Current MAChine Name and Logged in User
Why Can't I Declare Static Methods in an Interface
How to Embed Binary Data in Xml
Spring Boot Multiple Datasource
Calculate the Display Width of a String in Java