在Java中,类可以引用包含它的另一个类的实例吗?

时间:2019-06-09 17:20:19

标签: java

class A {
    private B b = new B();
}

class B {
    private A a;
    public void setA(A a){
        this.a = a
    }
}

setA在启动A的实例之后被调用。我想这样做,因为A有一个B要在其中调用的方法。

3 个答案:

答案 0 :(得分:3)

当然,这种语言允许这样做。

但是通过执行此操作,可以创建称为 circular 的依赖项。 A需要B,而B需要A。在许多情况下,这被视为不良做法。

因此,真正的答案是退后一步,看看您要解决的问题。然后设计一个不会产生循环依赖的解决方案!有时双向连接是必要的,但通常,它很快就会成为以后潜在问题的根源。因此,除非您仔细评估了自己的选择并且没有找到更好的方法,否则不要购买这种解决方案。

例如,接口B需要的方法可能会有所帮助。然后,您的B对象只需要该接口的一个实例(可以是一个A)。

答案 1 :(得分:3)

这里A组成B。

class A {
    private B b = new B();
}

这里B组成A:

class B {
    private A a;
    public void setA(A a){
        this.a = a
    }
}

没有设计判断,假设您处于需要双向依赖的情况下,应避免使用初始化程序或构造函数来创建此类的实例,因为您需要A的实例来创建B,反之亦然。像您的示例代码中那样,以非对称方式进行此操作以某种方式隐藏了这两个类之间的关系。 因此,您可以使用设置器或工厂方法来使其更清晰。

更好的方法:

class A {
    private B b;
    public void setB(B b){
        this.b = b;
    }
}    

class B {
    private A a;
    public void setA(A a){
        this.a = a
    }
}

A a = new A();
B b = new B();
a.setB(b);
b.setA(a);

或者采用工厂方法,您可以根据客户的需求POV依赖于A或B类来公开工厂方法:

class A{
    // ...
    public static A ofWithB(){
      A a = new A();
      B b = new B();
      a.setB(b);
      b.setA(a);
      return a;     
    }
}

A a = A.ofWithB();
B b = a.getB();

答案 2 :(得分:1)

任何时间代码(在您的示例中为B)都引用了不同类的实例(在您的示例中为A),这些规则控制其对该实例的成员的访问方式(方法和字段)相同:

  • 如果成员是private,则B无法访问
  • 如果成员是protected,则只有BB在同一类中,或者A是以下子类的情况下,B才能访问它A
  • 如果成员是程序包私有的(如果在类中,则没有访问修饰符),则B仅在BA在同一程序包中时才能访问它
  • 如果成员是public,则B可以访问它

(在界面中,没有访问修饰符= public,并且您不能有其他访问修饰符。)

该实例是否保存在B实例的字段上并不重要。唯一重要的是试图执行访问的代码位于哪个类中。

请参见Controlling Access to Members of a Class