4

Example: If I have two classes: A and B. both class can call a method in C (example: the init() method)

From C, how do we know where the call is from (from Class A or Class B) ?

Gijs
  • 5,201
  • 1
  • 27
  • 42
Karim Oukara
  • 2,638
  • 8
  • 38
  • 51
  • 4
    You can look at the stack trace but this is rarely a good idea (and its relatively slow) You should instead pass to C all the important information. BTW You can pass a class as an argument e.g. `init(A.class);` – Peter Lawrey Oct 11 '12 at 07:58
  • 4
    Technically it might be interesting, but in general code should not depend on the caller, it should depend on its parameters – stefan bachert Oct 11 '12 at 08:03
  • can you give me an exemple ? thank you – Karim Oukara Oct 11 '12 at 12:16
  • See also http://stackoverflow.com/questions/3178249/how-can-i-know-which-method-call-my-method?rq=1 – DNA Oct 31 '12 at 11:25
  • possible duplicate of [In Java, how do I find the caller of a method using stacktrace or reflection?](http://stackoverflow.com/questions/421280/in-java-how-do-i-find-the-caller-of-a-method-using-stacktrace-or-reflection) – DNA Oct 31 '12 at 11:28

4 Answers4

3

To do it right, you should provide C's method with that information, for example via an enum or class parameter:

public void init(Object otherArg, Class<?> caller) {
    ...
}

or

public void init(Object otherArg, CallerEnum caller) {
    ...
}

But if you don't care, there is another way using the stack trace. Have a look at Get current stack trace in Java and use the second StackTraceElement from the top of the stack to get the method that called the current one.

Community
  • 1
  • 1
rolve
  • 10,083
  • 4
  • 55
  • 75
3

This may be useful:

StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); 
  • you can use this to get the stack trace of the current thread in a StackTraceElement array where the first element of the array is the most recent method invocation sequence on the stack

  • provided the returned array is of non-zero length. StackTraceElement has methods like getClassName, getMethodName, etc., which one can use to find the caller class name or method name.

sohel khalifa
  • 5,602
  • 3
  • 34
  • 46
1

Taken from somewhere of the web...

private static final int CLIENT_CODE_STACK_INDEX;

static {
    // Finds out the index of "this code" in the returned stack trace - funny but it differs in JDK 1.5 and 1.6
    int i = 0;
    for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
        i++;
        if (ste.getClassName().equals(MyClass.class.getName())) {
            break;
        }
    }
    CLIENT_CODE_STACK_INDEX = i;
}

public static String getCurrentMethodName() {
    return Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX].getMethodName();
}
public static String getCallerMethodName() {
    return Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX+1].getMethodName();
}
urir
  • 1,960
  • 3
  • 23
  • 40
  • 1
    I suspect the different depth depends on the number of call levels inside the getStackTrace which is called before the snapshot is taken. It could differ between vendors as well. – Peter Lawrey Oct 11 '12 at 08:02
  • Executed on class X.foo - will return "foo", the static block is to prevent the problem you referred. – urir Oct 11 '12 at 08:06
  • 1
    I was trying to explain why the static block was needed as you had the comment `funny but it differs in JDK 1.5 and 1.6` – Peter Lawrey Oct 11 '12 at 08:08
0

I found an easier solution (for me :D )

public <T> void init(Class<T> clazz) {
     if (!clazz.getSimpleName().equals("MyClassName")) {
          // do something
     }else{
          // do something
     }
}
Karim Oukara
  • 2,638
  • 8
  • 38
  • 51