簡體   English   中英

java的this()構造函數重載,如何在this()之前執行代碼

[英]java Constructor overload with this(), how to execute code before this()

今天,我在一個大型項目中遇到了一個有趣的情況。 一個類有幾個構造函數,它們使用this()相互調用,最后將調用init(),build()等。 我想設置一個標志,然后調用this()和整個繁瑣的過程,但是調用this()應該是第一個。

如何在此類內修改代碼,而無需修改Contructor標頭和設置標志? :)

我知道這聽起來像hackhack,也許這不是在學校學到的,這就是為什么至少對我來說有趣。 對於其他人,在某些情況下也可能有用。

這是一個基本示例,我做了一些修改以模擬實際問題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-reflection-invoking-constructor-parameters.html某些IDE足夠聰明,即使使用Class.forName(“ java.awt .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.
    }
}

我也會考慮重構其余部分。 數百萬行代碼? 天啊。

今天,我在一個大型項目中遇到了一個有趣的情況。 一個類有幾個構造函數,它們使用this()相互調用,最后將調用init(),build()等。 我想設置一個標志,然后調用this()和整個繁瑣的過程,但是調用this()應該是第一個。

你不能 在我看來,該標志應該是傳遞給鏈式(可能是私有的)構造函數的參數之一:

public Rectangle() {
  this(false, 0, 0, 0, 0);
}

public Rectangle(int width, int height) {
   this(true, 0, 0, width, height);
}

private Rectangle(boolean flag, int x, int y, int width, int height) {
    // Use everything including flag.
}

可以在調用鏈式構造函數之前調用代碼,但是:

  • 它基本上必須是一種方法調用,用於為鏈式構造函數創建參數之一
  • 它不能使用this

好,必須首先調用this() ,但是要解決此問題的一種“怪異”方法是使用工廠設計模式並使用靜態方法,它應該看起來像這樣:

public static Rectangle createRectangle(int width, int height) {
   //do some some stuff
   return new Rectangle(int x, int y, width, height)
}

我將修改結構,以便每個構造函數都使用適當的參數調用init()方法。 然后,在init()方法中,您可以執行4-arg構造函數中當前的操作。 這使構造函數可以設置標志等,而實際的初始化工作將在以后進行,並且可以使它們尊重標志。

在這種情況下,我會選擇一個帶有額外參數的私有構造函數。

[...]
public Rectangle() {
    this(true, 0, 0, 0, 0);
}
public Rectangle(int width, int height) {  
    this(false, 0, 0, width, height);
}
public Rectangle(int x, int y, int width, int height) {
    this(true, x, y, width, height);
}
private Rectangle(boolean flag, int x, int y, int width, int height) {
    this.flag = flag;
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    init();
}
[...]

通常,最好避免對構造函數做太多事情。

正如您鏈接到的文檔所說:

如果存在,則另一個構造函數的調用必須是該構造函數的第一行。

將標志作為參數傳遞給構造函數,並將其存儲。 (如果用來確定使用哪個構造函數創建實例的話。)我不明白為什么您不只是在主構造函數中首先調用神秘代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM