0 java constructor overloading
今天我在一个巨大的项目中遇到了一个有趣的情况 一个类有几个构造函数,它们用this()相互调用,最后会调用init(),build()等等.我想设置一个标志,然后调用this()和整个繁琐的过程,但调用this()它应该是第一个.
如何在不修改Contructor标头并设置标志的情况下修改此类中的代码?:)
我知道这听起来像是hackish,也许这不是在学校学到的,这就是为什么至少对我来说有趣.对于其他人来说在某些情况下也很有用.
这是一个基本的例子,我做了一些修改来模拟真正的问题,即init()方法. 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
}
}
Run Code Online (Sandbox Code Playgroud)
我有一个简单的实现,但在我写这个问题之前我也得到了第二个.
我的重要问题没有答案,但我希望这将是,我可以接受某人的答案,谁想要建立声誉.
init()方法不能被编码两次或者代码的逻辑写入2个位置,因为它不是一个好的编程范例,并且可能调用几百万行代码.
-------------编辑添加----------------
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");
}
Run Code Online (Sandbox Code Playgroud)
-----------------------编辑添加解决方案1 - 一个非常简单的案例
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;
}
Run Code Online (Sandbox Code Playgroud)
之所以在一个巨大的项目中无法改变功能签名是(其中之一)动态加载和反射用法: http://tutorials.jenkov.com/java-reflection/constructors.html http:// tutorials .jenkov.com/java的反射/动态类加载-reloading.html
http://www.java-forums.org/java-lang/7896-object-reflection-invoking-constructor-parameters.html 即使使用Class.forName("java.awt",某些IDE也足够智能地查找对此类的引用.Rectangle"),如果你有源,但如果他们在第三方库(插件),可能不是.许可证检查例程想隐藏自己,开发人员有点经验将"Rectangle"拆分为"Rect"+"tagle",甚至更复杂(decodeString)(但这已经足够了.非常怀疑你的超级智能编辑器可以找到参考比:)
下一个解决方案可以是反射(这是我在这里输入的第二个解决方案,我在上面写过) - 没人提到过
总之一句:你做不到.Java之前禁止调用任何东西this,所以放弃了这个想法.
这可能会引发几百万行代码.
这本身就是一个问题.如果我是你,我会非常担心.
这听起来不像构造函数,更像是一个Builder模式.也许您应该考虑构造函数的替代方案.
你需要一个设置标志的构造函数,即使它是私有的.
public class Rectangle {
private int x, y;
private int width, height;
private boolean flag;
private Rectangle(int x, int y, int w, int h, boolean doInit) {
this.x = y;
this.y = y;
this.width = w;
this.height = h;
this.flag = doInit;
// Do what you must after this; adjust other ctors accordingly.
}
}
Run Code Online (Sandbox Code Playgroud)
我也考虑重构其余部分.数百万行代码?天啊.