0

When I call on a method in a class, the method will get the java.lang.Class that called on it using sun.reflect.Reflection.getCallerClass(2). This is not what I want. I want the Reflection to return the class Object that called on it (i.e. if I call the method from the Bar class, the Reflection.getCallerClass() returns an object of type Bar)

Let's suppose I have this class:

public class Foo {
    public static void printOutCallerObject() {
        System.out.println(classTypeThatCalledOnMethod);
    }
}

Called by:

public class Bar {
    public static void main(String[] args) {
        Foo.printOutCallerObject();
    }
}

And then the program would print out "Bar".

Lucas Baizer
  • 189
  • 1
  • 2
  • 10
  • This isn't clear. Are you saying that you want to retrieve the actual calling **instance**, rather than just the class? – Oliver Charlesworth Jul 19 '15 at 18:49
  • There isn't a really good way to do this. It *is* possible, but it is also often really bad design! The only time I've seen use for this is logging, and loggers should handle that for you automatically... You *could* use `Thread.currentThread().getStackTrace()` to get this information. – Daniel Jul 19 '15 at 18:49
  • Why would you want to do this? Sounds like an [XY problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) – Vince Jul 19 '15 at 18:53
  • @VinceEmigh a common use case is logging and related code inspection. There certainly may be better ways to go about it (e.g. stepping through with a debugger), but it's not totally unreasonable to want this. – dimo414 Jul 19 '15 at 18:56
  • @dimo414 This is what aspect oriented programming was designed for. AspectJ could help him achieve what he wants. But as I said before, he's asking about how he feels logging should be done, rather than asking about how he should log. He could get better answers by avoiding the XY problem. He should be using some kind of logging system that ensures logging logic isn't mixed with other logics – Vince Jul 19 '15 at 19:09
  • Then just say "Another way to inspect your code, assuming that's what you'd like to do, is with [aspect-oriented programming](https://en.wikipedia.org/wiki/Aspect-oriented_programming). The [AspectJ](http://www.eclipse.org/aspectj/) library was built for these sorts of problems." and let OP decide if that's what they need. I, for one, would absolutely not bother learning AOP just to do some basic stack inspection. – dimo414 Jul 19 '15 at 19:13
  • @dimo414 My point was, if he asked his question in a better fashion, he could get better answers. Ones that not only describe what he wants, but could lead him in a better direction. The better the question, the better the answers. For all you know, what he wants to do is *not* basic, and what you suggested would cause a huge mess when scaling up. – Vince Jul 19 '15 at 20:59
  • @VinceEmigh it's a good point, and worth making. But there's no need to be accusative and assume OP is mistaken when you could, without judgment, simply offer an alternative. – dimo414 Jul 19 '15 at 21:09
  • @dimo414 He wasn't mistaken. It was apparent to me he wanted this for logging purposes, but he could have asked his question in a way that'll gain him more information. What I asked ("what is this for?") is how I introduce the XY problem; the answer they give me is a question that'll benefit them a lot more. It was to introduce him to asking questions that'll benefit him more – Vince Jul 20 '15 at 01:02

1 Answers1

2

Here's a quick demo of how you can get the calling class - you cannot get the calling object unless you pass it to the method because it is not on the stack.

public class ReflectDemo {
    public static class Foo {
        public static void printOutCallerObject() {
            StackTraceElement[] trace = Thread.currentThread().getStackTrace();
            // trace[0] is Thread.getStackTrace()
            // trace[1] is Foo.printOutCallerObject()
            // trace[2] is the caller of printOutCallerObject()
            System.out.println(trace[2].getClassName());
        }
    }

    public static class Bar {
        public static void barMain() {
            Foo.printOutCallerObject();
        }
    }

    public static void main(String[] args) {
        Foo.printOutCallerObject();
        Bar.barMain();
    }
}

This prints:

ReflectDemo
ReflectDemo$Bar

And Foo.printOutCallerObject(); will print out the class of whatever code calls it. The call to Thread.currentThread().getStackTrace() isn't cheap, so be aware that you may incur some runtime costs. This pattern is often used for logging, to record which piece of code triggered the logging call.

dimo414
  • 47,227
  • 18
  • 148
  • 244
  • This isn't what I need- I need the trace to return a `Bar` Object. Not a Class Object. – Lucas Baizer Jul 20 '15 at 02:11
  • @LucasBaizer Like I said, that isn't possible. The calling object is not available on the stack. The workaround is to pass `this` as a parameter to `printOutCallerObject()`. – dimo414 Jul 20 '15 at 04:05