使用反射获取“拥有”类中字段的值

时间:2014-04-03 19:21:13

标签: java reflection

无论如何都要获取另一个类中调用的类的实例? 例如,如果Foo类具有Bar类和Clazz类的实例, 无论如何通过Clazz类使用反射来获取Bar类的实例?

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
}

1 个答案:

答案 0 :(得分:0)

Bar"中没有Foo的实例,因为您尚未实例化Foo。不,就目前而言,Clazz不知道任何可能在某个领域引用它的类,你必须添加它。

实现此目的的一种方法是通过正确使用getter并跟踪父对象:

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());
    }
}

或者,甚至更好,因为Clazz不再依赖Foo而您不必担心部分构建的Foo,只需通过Bar } 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);
    }
}

第二种方式更自然地表示您的实际依赖关系(Clazz并不关心它来自Foo,它只关心拥有Bar)。

第一种方式的优点是允许Foo随时更改其Bar(我注意到您未在final b中声明Foo)并Clazz 1}}注意更新的值;当然,使用Clazz#setBar(Bar b)可以完成同样的事情,而不会在Foo上引入错误依赖。


那里不需要反思。但是,请在下面回复您的评论:

  

我的问题的实际目的是关于我们在大学CS课程中参加的战舰比赛。我们被允许互相攻击,以便找到对手的船只部署。

不幸的是,那么 - 假设你的代码片段是代码结构的准确表示 - 除非Clazz存储创建它的Foo实例(或者是非静态内部类一个Foo),你运气不好。无法通过反射找到具有Foo的{​​{1}}(从而获得Clazz),因为反射不提供获取所有实例化{{1}的列表的方法1}}来搜索。如果您知道Bar,那么您可以获得其Foo成员,但您必须知道要开始的Foo实例。您可能会在某处注入一些聪明的字节代码来跟踪它,但有点高级,但请参阅Java Bytecode Instrumentationhere for an overview

然后写下:

  

我已经读过如果你知道类的名字,有办法通过反射找到Foo类的实例。

不,不幸的是(如果我理解正确的话),there is no way to get an existing instance of a Foo given only its class name

  

如果找到Foo课程,我还能找到Bar课程吗?

如果您有b的实例,并且您知道字段名称为Foo,则可以执行以下操作:

Foo

请参阅Class.getDeclaredField()Field.get()