1

Let's say I have a class that instantiates and uses another class. From the second class, is it possible to gain access to the first one? For example:

public class A {
    public B obj = new B();

    public void something() {
        b.somethingElse();
    }
}

public class B {
    public void somethingElse() {
        A owner = getCallingObject();
        //the object of class A that called b.somethingElse() is now stored in owner
    }

    public Object getCallingObject() {
        // ?????
        // returns the A that instantiated/owns this B
    }
}

I know how to get the Class of that object using something like this:

private String getCallerClassName() {
    StackTraceElement[] stElements = Thread.currentThread().getStackTrace();
    for (int i = 1; i < stElements.length; i++) {
        StackTraceElement ste = stElements[i];
        if (!ste.getClassName().equals(B.class.getName()) && ste.getClassName().indexOf("java.lang.Thread") != 0)
            return ste.getClassName();
    }
    return null;
}

which I got from a different question: How to get the caller class in Java. Is there a way to get a pointer to the caller object?

Juan Carlos Mendoza
  • 5,736
  • 7
  • 25
  • 50
Hamrobe
  • 41
  • 1
  • 1
  • 2
  • 4
    Sorry, Java doesn't work that way. If you want a back reference to `A` in `B`, you need to create one yourself. – Joe C Oct 25 '17 at 22:29
  • 6
    `b.somethingElse(this);` – JB Nizet Oct 25 '17 at 22:30
  • If you can't change method signatures or pass reference of `A` to `B` then you can use ThreadLocal where you can put `A` into the ThreadLocal before calling `b.somethingElse();` and get it from ThreadLocal inside `somethingElse` method. You can further automate this using AOP. – tsolakp Oct 25 '17 at 23:27

1 Answers1

1

If you control the source code, and if B can only be created by an A object, you could make B a non-static inner class, and then you would automatically get a reference back to the creator of the class, through the A.this pointer. Note this isn't the caller of B::somethingElse(), but the creator of B, which may or may not be the same thing, depending on your use case.

public class A {
    public B obj = new B();

    public void something() {
        obj.somethingElse();
    }

    void thereAndBackAgain() {
    }

    public class B {

        public void somethingElse() {
            A owner = A.this; 
            owner.thereAndBackAgain(); 
        }
    }
}
AJNeufeld
  • 8,526
  • 1
  • 25
  • 44
  • Is it possible without nested classes and not changing A? – Hamrobe Oct 25 '17 at 23:04
  • Without nested classes? Sure. Without changing `A` at all? Probably not. You’d at least have pass `this` to either B’s constructor `new B(this)` or the call `obj.somethingElse(this)`, both of which is changing `class A { ... }` code. Otherwise you have no guarantee that the “owner”/“caller” is even an object of type `A`; some class `Q` could create your public `B` and invoke the public `somethingElse` method. – AJNeufeld Oct 26 '17 at 00:42
  • Thank you! This actually helped a lot – Hamrobe Oct 26 '17 at 00:50