Сегодня я встретил интересную ситуацию в огромном проекте.Класс имеет несколько конструкторов, которые вызывают друг друга с помощью this (), и в конце будут вызывать init (), build () и так далее.Я хотел установить флаг и после этого вызывать this () и весь громоздкий процесс, но при вызове this () он должен быть первым.
Как я могу изменить код внутри этого класса, не изменяяЗаголовки Contructor и установить флаг?:)
Я знаю, это звучит хакерски, и, возможно, этому не учат в школах, поэтому это интересно, по крайней мере, для меня.Для других тоже может быть полезно в некоторых случаях.
Вот базовый пример, я сделал несколько модификаций, чтобы смоделировать реальную проблему, метод 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
}
}
Я получил 1 простую реализацию, но пока я не написал этот вопрос, я получил и второй.
Мои важные вопросы остались без ответа, но я надеюсь, что это будет иЯ могу принять чей-то ответ, который хочет создать репутацию.
Метод 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");
}
----------------------- Редактировать добавление решения 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;
}
Причина, по которой в огромном проекте невозможно изменить, подписи функций (одна из них) - динамическая загрузка и использование отражения: 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-отражение-invoking-constructor-parameters.html Некоторые IDE достаточно интеллектуальны, чтобы найти ссылки на этот класс даже с Class.forName ("java.awt.Rectangle"), если у вас есть tИсточники, но если они находятся в сторонних библиотеках (плагинах), то, вероятно, нет.Подпрограмма проверки лицензии хочет скрыть себя, и разработчик, немного опытный, разделит «Rectangle» на «Rect» + «tagle» или даже более сложный (decodeString) (но этого достаточно. Очень сомневаюсь, что ваш суперинтеллектуальный редактор можетнайти ссылки, чем:)
Следующее решение может быть с отражением (это было второе решение, которое я набрал здесь и написал выше) - пока никто не упомянул