简体   繁体   中英

Obtain value of a field in an “owning” class using reflection

Is there anyway to obtain an instance of a class called in another class? For example, if Foo class has an instance of a Bar class and a Clazz class, is there anyway to obtain the instance of the Bar class through the Clazz class using reflection?

public class Foo{
  Bar b = new Bar();
  Clazz c = new Clazz();
}

public class Bar
{
   int i = 3;
}

public class Clazz
{
  //Code to get the instance of Bar running in Foo using Reflection
}

There is no "instance of Bar running in Foo ", since you have not instantiated a Foo . And no, as it stands, Clazz has no knowledge of any classes that may refer to it in a field, you would have to add that.

One way to do this is via proper use of getters and keeping track of the parent object:

public class Foo {
    Bar b = new Bar();
    Clazz c = new Clazz(this); // be warned: `this` is not fully constructed yet.
    public Bar getB () { return b; }
}

public class Clazz {
    private final Foo owner;
    public Clazz (Foo owner) {
        this.owner = owner;
    }
    public void example () {
        doSomething(owner.getB());
    }
}

Or, even better, since Clazz no longer depends on Foo and you don't have to worry about a partially constructed Foo , just pass the Bar to Clazz :

public class Foo {
    Bar b = new Bar();
    Clazz c = new Clazz(b); 
}

public class Clazz {
    private final Bar bar;
    public Clazz (Bar bar) {
        this.bar = bar;
    }
    public void example () {
        doSomething(bar);
    }
}

The second way more naturally indicates your actual dependencies as well ( Clazz doesn't care that it comes from a Foo , it only cares about having a Bar ).

The first way has the advantage of allowing Foo to change its Bar at any point (I noticed you did not declare final b in Foo ) and have Clazz be aware of the updated value; of course, that same thing can be accomplished with a Clazz#setBar(Bar b) without introducing a false dependency on Foo .


There isn't much need for reflection there. However, responding to your comment below, where you write:

The actual purpose of my question regards to a battleship tournament we are having in a CS class at my University. We are allowed to hack each other in order to find the ship deployment of our adversary.

Unfortunately, then -- presuming your snippet is an accurate representation of the code structure -- unless Clazz stores an instance of the Foo that created it (or is a non-static inner class of a Foo ), you are out of luck. There is no way with reflection to find the Foo that has that Clazz (and thus get the Bar ), because reflection does not provide a means of getting a list of all instantiated Foo s to search through. If you know the Foo then you can get its b member, but you have to know about the Foo instance to begin with. You might be able to inject some clever byte code somewhere to track it though, a bit advanced but see Java Bytecode Instrumentation , or here for an overview .

You then write:

I have read that there is a way to find the instance of the Foo class through reflection if you know the name of the class.

No, unfortunately (if I understand you correctly), there is no way to get an existing instance of a Foo given only its class name .

Is there anyway for me to find the Bar class if I find the Foo class?

If you have an instance of a Foo , and you know the field name is b , then you can do:

Foo theFoo = ...; // your Foo instance

Field field = Foo.class.getDeclaredField("b");
Bar theBar = (Bar)field.get(theFoo); // get field "b" value from 'theFoo'.

See Class.getDeclaredField() and Field.get() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM