How to initialize a circular dependency (final fields refer to each other)?

How do you initialize this:

class A { final B b; A(B b) { this.b = b; } } class B { final A a; B(A a) { this.a = a; } } 

DI frame, reflection, better design?

Motivation and use case (added) :

My specific use case makes it easy to access a field in subclasses A and B Therefore, I insert them in order to refer to them by fields in derived classes soon without the need to explicitly indicate in each subclass.

There is also a DI recommendation that objects should be more immutable: Guice best practices and anti-patterns .

+6
source share
3 answers

You can use factory method

 class A { final B b; A(B b) { this.b = b; } } abstract class B { final A a; B() { this.a = constructA(); } protected abstract A constructA(); } public class C { public static void main(String []args){ new B(){ protected A constructA(){ return new A(this); } }; } } 
+5
source

Although it may look dirty, I prefer to replace one of the final links with Supplier (for example, in Guava or Java 8 ), for example:

 class A { final Supplier<B> b; A(Supplier<B> b) { this.b = b; } // keeping this constructor just for usability sake A(B b) { this.b = ofInstance(b); // using Guava Suppliers.ofInstance here } } class B { final A a; B(A a) { this.a = a; } } public static void main(String[] args) { // using MutableSupplier.create() static factory method MutableSupplier<B> bRef = create(); A a = new A(bRef); B b = bRef.set(new B(a)); } 

where the MutableSupplier looks something like this:

 import com.google.common.base.Supplier; public class MutableSupplier<T> implements Supplier<T> { private boolean valueWasSet; private T value; private MutableSupplier() { } @Override public T get() { if (!valueWasSet) { throw new NullPointerException("Value has not been set yet"); } return value; } public T set(final T value) { if (valueWasSet) { throw new IllegalStateException("Value has already been set and should not be reset"); } this.value = value; this.valueWasSet = true; return value; } public static <T> MutableSupplier<T> create() { return new MutableSupplier<T>(); } } 

I know that the mutability of MutableSupplier looks super-ugly for immutability enthusiasts, but I found that using such methods is more or less acceptable in such cases :)

+1
source

What you have is circular dependence. The only way I can think of is not to declare the fields as final, but to inject your dependency using installer injection instead of constructor injection.

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

Source: https://habr.com/ru/post/957485/


All Articles