1

How do I know which class called a method?

class A {
   B b = new B();

   public void methodA() {
    Class callerClass = b.getCallerCalss(); // it should be 'A' class
   } 
}

class B {
 public Class getCallerCalss() {
   //... ???
   return clazz;
 }
}
keyser
  • 18,829
  • 16
  • 59
  • 101
ses
  • 13,174
  • 31
  • 123
  • 226
  • Is it possible to pass Class as parameter to getCallerClass()? – kosa Sep 24 '12 at 15:12
  • 1
    about editing. - yeah.. sorry for that. thinking on demand.. like refactoring.. TDD kind of. – ses Sep 24 '12 at 15:13
  • passing class as parameter - it is possible but not nice i guess. maybe some magic with reflection could help – ses Sep 24 '12 at 15:13
  • "How to who" "calss" != "class" != "clazz" – nana Sep 24 '12 at 15:14
  • This question might help: [Java logger that automatically determines caller's class name](http://stackoverflow.com/q/80692/1343161) – Keppil Sep 24 '12 at 15:15
  • @ses: The editing on the fly is not a very good idea. If you'd like a prompt answer instead of hoping for an eventual "long tail" one, you only have a fairly short window of time to attract attention to your question. If it's cryptic or broken, it's more likely people will navigate to one that isn't. – millimoose Sep 24 '12 at 15:27
  • Can you give us more information on why you need to know the class of the caller? Generics may be more appropriate depending on what you are trying to do. – km1 Sep 24 '12 at 15:31

4 Answers4

4

This is easily done with Thread.currentThread().getStackTrace().

public static void main(String[] args) {
    doSomething();
}

private static void doSomething() {
    System.out.println(getCallerClass());
}

private static Class<?> getCallerClass() {
    final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
    String clazzName = stackTrace[3].getClassName();
    try {
        return Class.forName(clazzName);
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
        return null;
    }
}

[3] is used because [0] is the element for Thread.currentThread(), [1] is for getCallerClass, [2] is for doSomething, and finally, [3] is main. If you put doSomething in another class, you'll see it returns the correct class.

Brian
  • 17,079
  • 6
  • 43
  • 66
3

There's a method of observing the stacktrace

StackTraceElement[] elements = Thread.currentThread().getStackTrace()

Javadoc

The last element of the array represents the bottom of the stack, which is the least recent method invocation in the sequence.

Johan Sjöberg
  • 47,929
  • 21
  • 130
  • 148
  • Why is it "not very nice"? Doing logic based on inspecting the stack trace is dubious design, but the method seems just fine if you can accept the performance hit. – millimoose Sep 24 '12 at 15:16
  • @millimoose, What I meant was the scenario feels more like a `Design` issue to me. – Johan Sjöberg Sep 24 '12 at 15:18
3

You can get the class name of the caller class by fetching the second element of the stack trace:

final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
System.out.println(stackTrace[1].getClassName());

The getClassName method of the StackTraceElement class returns with a String so you won't get a Class object unfortunately.

KARASZI István
  • 30,900
  • 8
  • 101
  • 128
0

Try Throwable.getStackTrace().

Create a new Throwable.. you don't have to throw it :).

untested:

Throwable t = new Throwable();
StackTraceElement[] es = t.getStackTrace();
// Not sure if es[0] would contain the caller, or es[1]. My guess is es[1].
System.out.println( es[0].getClass() + " or " + es[1].getClass() + " called me.");

Obviously if you're creating some function (getCaller()) then you'll have to go another level up in the stack trace.

Kashyap
  • 15,354
  • 13
  • 64
  • 103