Today I met an interesting situation in a huge project.
A class has several constructors which calls each other with this(), and at the end will call the init(), build() and so on. I wanted to set a flag and after that call the this() and the whole cumbersome process, but calling this() it should be the first.
How can I modify a code inside this class, without modifying the Contructor headers and set the flag? 🙂
I know it sounds like hackish, and maybe this aren’t learned at schools, that’s why is interesting at least for me. For others can be usefull too in some cases.
Here is a basic example, I did a few modification to simulate the real problem, the init() method.
http://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html
public class Rectangle {
private int x, y;
private int width, height;
private boolean flag;
public Rectangle() {
// execute code here, before this(), how? -set the flag true for eg.
this(0, 0, 0, 0);
}
public Rectangle(int width, int height) {
// execute code here to, something different as above, before this(), how?
this(0, 0, width, height);
}
public Rectangle(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
init();
}
private void init(){
if(flag){
... do something new, else or different as the original, maybe return, even exit too
}
... do something... the old code
}
}
I got 1 easy implementation, but until I wrote this question I got the second one too.
My important questions are unanswered, but I hope this will be and I can accept somebody’s answer, who want to build up reputation.
The init() method can’t be coded twice or the logic of the code written in 2 places, because it is not a good programming paradigm, and that invokes maybe a few millions line of the code.
————- Edit added —————-
There is a way to known from which constructor was called: the full parametrized one or anything else with this() -I hope it gives more idea:
public Rectangle(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
try {
throw new RuntimeException("Hacking use a lot of imagination");
} catch (Exception ex) {
StackTraceElement[] stackTraces = ex.getStackTrace();
// the first element is just above, no reason to check
String thisClassName = getClass().getName();
if (stackTraces[1].getClassName().equals(thisClassName)) {
if (stackTraces[1].getMethodName().equals("<init>")) {
flag = true;
}
}
}
init();
}
private void init() {
if (flag) {
System.out.println("\"... do something new, else or different as the original, maybe return, even exit too\"");
}
System.out.println("\"... do something... the old code");
}
———————– Edit adding solution 1 -a very simple case
public Rectangle() {
// execute code here, before this(), how? -set the flag true for eg.
this(doVeryBanalHack(0, false), 0, 0, 0);
}
public Rectangle(int width, int height) {
// execute code here to, something different as above, before this(), how?
this(doVeryBanalHack(0, false), 0, width, height);
}
public Rectangle(int x, int y, int width, int height) {
this.x = doVeryBanalHack(x, true);
this.y = y;
this.width = width;
this.height = height;
// TODO deal with concurrency if you are in multithreaded environment, otherwise is done
this.flag = nextValueOfFlag;
init();
....}
private static boolean nextValueOfFlag;
private static int doVeryBanalHack(int retValue, boolean flagValue) {
System.out.println("\"execute code here, before this() it is too simple, it is banal static function\");
// TODO deal with concurrency if you are in multithreaded environment
nextValueOfFlag = flagValue;
}
the reason why in a huge projet can’t changed the function signatures are ( one of them) the dynamic loading, and reflection usage: http://tutorials.jenkov.com/java-reflection/constructors.html
http://tutorials.jenkov.com/java-reflection/dynamic-class-loading-reloading.html
http://www.java-forums.org/java-lang/7896-object-reflection-invoking-constructor-parameters.html
Some IDE are enough intelligent to find refferences to this class even with Class.forName(“java.awt.Rectangle”), if you have the sources, but if they are in third party libraryes ( plugins), than probably not. A licence checking routine want to hide himself and the developper is a bit experienced will split the “Rectangle” as “Rect” + “tagle” , or even more complex (decodeString) ( but this is enough. Highly doubt your super intelligent editor can find references than 🙂
The next solution can be with reflection ( that was the second one solution which I got typing here and I wrote above) -nobody mentioned yet
In this case, I’d go for a private constructor with an extra argument.
As a general rule, it’s generally good to avoid doing to much with constructors.