简体   繁体   中英

In Java, can a class reference the instance of another class which contains it?

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

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

setA is called after an instance of A has been initiated. I want to do this becase A has a method that B wants to call inside it.

Sure, the language allows to do that.

But by doing this, you create what is called a circular dependency. A needs B, and B needs A. That is considered bad practice in many cases.

So, the real answer would be to step back and look at the problem you intend to solve. And to then design a solution that does not create a circular dependency! Sometimes bidirectional connectivity is necessary, but in general, it can quickly become a source for potential problems later in. So do not buy into such a solution unless you have carefully evaluated your options and you didn't find a better way.

It might be helpful for example that method that B needs in an interface. Then your B object only needs an instance of that interface (which could be an A under the covers).

Here A composes B.

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

And here B composes A :

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

No design judgement, supposing that you are in a case where the bidirectional dependency is needed, you should avoid initializer or constructor to create instances of this class since you need an instance from A to create B and reversely. Making this in an asymmetric way as in your sample code hides in a some way the relationship between these two classes.
So you could use a setter or a factory approach to make it clearer.

Setter approach :

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

Or with a factory approach where you can rely on A or B class to expose the factory method according to the client need POV :

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

Any time code (in B in your example) has a reference to an instance of a different class ( A in your example), the rules governing its access to that instance's members (methods and fields) are the same:

  • If the member is private , B cannot access it
  • If the member is protected , B can access it only if B and A are in the same class, or B is a subclass of A
  • If the member is package-private (no access modifier if it's in a class), B can only access it if B and A are in the same package
  • If the member is public , B can access it

(In an interface, no access modifier = public and you can't have other access modifiers.)

It doesn't matter whether the instance is held on a field of an instance of B . The only thing that matters is what class the code trying to perform the access is in.

See Controlling Access to Members of a Class

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