Always execute method after constructor in Java

I have a situation where I always need to run a specific bit of code, which depends on the object itself

public abstract class A{ public A(X x){ //init A stuff x.getAList("stuff").add(this); x.getAList("otherstuff").add(this); } } public class B extends A{ public B(X x){ super(x); //init B stuff } } public class C extends A{ public C(X x){ super(x); //init C stuff x.getAList("otherstuff").remove(this); x.getAList("morestuff").add(this); } } public class SomeClass{ private X someX; public A somefunc(boolean b){ if(b){ return new B(someX); }else{ return new C(someX); } } } 

The problem is as follows. In this example, I use this in the constructor. If another thread tries to access the object through someX.getAList, this may cause the thread to gain access to the object before the constructor finishes work.

You can do this so that the object is added to ALIST using somefunc

 public class SomeClass{ private X someX; public A somefunc(boolean b){ A a; if(b){ a = new B(someX); someX.getAList("stuff").add(a); someX.getAList("otherstuff").add(a); }else{ a = new C(someX); someX.getAList("stuff").add(a); someX.getAList("morestuff").add(a); } return a; } } 

The problem is that B and C can also be created elsewhere, and that each time B or C is created, they must be added in this way. I do not want to add an object to AList so that it is responsible for the user, but for the class. I also do not want the user to call the init function, which does this for them. On the other hand, I don't need concurrency problems.

Is there a way or template that allows this to be implemented?

Golang has something like defer that allows you to run a piece of code after the function / method / constructor completes.

+5
source share
2 answers

Make Factory-Method for the super and subclass and make the constructors private, forcing everyone who wants the instance to use the factory method. The factory method is a method that returns a fully constructed instance. When the instance is fully constructed (after the constructor has been called in the factory method), add the instance to the list, so no thread can get an incomplete / unfinalized instance.

The point of Factory-Method is to strictly isolate all initialization code from any non-initializing code in order to avoid access to uninitialized fields and their impact. It can also serve as a selector for users, automatically returning a suitable (sub) type, without the need to specify. ( Interesting design patterns )

 abstract class A{ protected A(){ //constructor code goes here } public void afterFinalisation(final X x) { x.getAList("stuff").add(this); x.getAList("otherstuff").add(this); } } class B extends A{ protected B(){ super(); //constructor code goes here } public static B create(final X x) { final B returnValue = new B(); returnValue.afterFinalisation(x); return returnValue; } } class C extends A{ protected C(){ super(); //constructor code goes here } @Override public void afterFinalisation(final X x) { super.afterFinalisation(x); x.getAList("otherstuff").remove(this); x.getAList("morestuff").add(this); } public static C create(final X x) { final C returnValue = new C(); returnValue.afterFinalisation(x); return returnValue; } } class SomeClass{ private final X someX = new X(); public A somefunc(final boolean b){ if(b){ return B.create(this.someX); }else{ return C.create(this.someX); } } } 

The credit for the constructor code goes into iteration cookies of my answer , I tried to avoid placing the code in protected constructors and worked with the init () method instead, which required a big inconvenient solution for the final fields.

+9
source

Taking a few design decisions from HopfullyHelpful , I ended up enjoying the best design:

 public abstract class A{ protected A(X x){ //constructor with all inits } protected A publish(X x) { x.getAList("stuff").add(this); x.getAList("otherstuff").add(this); return this; } } class B extends A{ protected B(X x){ super(x); //constructor with all inits } protected B publish(X x) { super.publish(x); return this; } public static B create(X x) { return new B(x).publish(x); } } class C extends A{ protected C(X x){ super(x); //constructor with all inits } protected void publish(X x) { super.publish(x); x.getAList("otherstuff").remove(this); x.getAList("morestuff").add(this); return this; } public static C create(X x) { return new C(x).publish(x); } } class SomeClass{ private X someX; public A somefunc(boolean b){ if(b){ return B.create(this.someX); }else{ return C.create(this.someX); } } } 
+1
source

All Articles