簡體   English   中英

鏈接構造函數時的Java null參數

[英]Java null arguments when chaining Constructors

假設我有一個包含多個構造函數的類,其中一個是復制構造函數(用於復制對象):

public class Rectangle {

    int width, height;

    public Rectangle(int width, int height) {
        this.width = width;
        this.height = height;
    }

    public Rectangle(Rectangle source) {
        this(source.width, source.height);
    }
}

有沒有什么辦法可以檢查copy-constructor中的source是否為null ,如果是,則拋出IllegalArgumentException 因為其他構造函數調用必須是我的構造函數中的第一個語句。

你可以這樣做:

public Rectangle(Rectangle source) {
     this(checkNotNull(source, "Source cannot be null").width, source.height);
}

private static <T> T checkNotNull(T t, String msg) {
    if (t == null) throw new IllegalArgumentException(msg);
    return t;
}

我同意Jon Skeet的觀點,在這種情況下, NullPointerException並不是一個壞的bevahiour。 唯一的問題是,在獲得NPE的情況下排長隊時,確定哪個對象為null可能有點困難,這就是更具體的消息可能有用的原因。

如果你不打擾拋出NullPointerException你也不能重新發明輪子並使用標准的java.util.Objects方法:

public Rectangle(Rectangle source) {
     this(Objects.requireNonNull(source, "Source cannot be null").width, source.height);
}

如果您的錯誤消息構建起來很昂貴,則可以提供Supplier<String> ,以便僅在實際需要時支付構造消息的成本:

 public Rectangle(Rectangle source) {
     this(Objects.requireNonNull(source, () -> explainError(source)).width, source.height);
}

是的,您可以使用輔助方法,如果需要將拋出異常,否則返回原始值...您可以在構造函數調用中調用它,因為您允許方法調用作為參數評估的一部分。

// In a helper class
public static <T> T checkNotNull(T value) {
    if (value == null) {
        throw new IllegalArgumentException();
    }
    return value;
}

然后用它作為:

public Rectangle(Rectangle source) {
    this(Helper.checkNotNull(source).width, source.height);
}

但是...我相信NullPointerException是建議的異常,無論如何都要扔在這里(例如,在Effective Java第2版中),你的現有代碼已經拋出了。 因此,您可能希望對現有代碼進行任何更改。

如果你想要一個像這樣的檢查的幫助器方法,但很高興它拋出NullPointerException ,我建議使用Guava及其Preconditions類,它有這個以及許多其他有用的檢查方法。

另請注意,Java 1.7引入了具有requireNonNull java.util.Objects ,因此您甚至不需要第三方庫。

一個教科書技巧是將初始化從構造函數移到方法中。 然后,你可以擁有你想要的任何代碼:

public class Rectangle {

    int width, height;

    public Rectangle(int width, int height) {
        init(width, height);
    }

    public Rectangle(Rectangle source) {
        if (source == null) {
            throw new IllegalArgumentException("source can't be null!");
        }
        init(source.width, source.height);
    }

    private void init(int width, int height) {
        this.width = width;
        this.height = height;
    }
}

如果你確實想要拋出IllegalArgumentException ,我認為最干凈的解決方案是使用靜態方法而不是構造函數:

public static Rectangle from(Rectangle source) {
    if (source == null) {
        throw new IllegalArgumentException("source can't be null!");
    }
    return new Rectangle(source.width, source.height);
}

或者你可以添加一個復制方法:

public Rectangle copy() {
    return new Rectangle(this.width, this.height);
}

我更喜歡后者,因為它不需要關注Rectangle可能為null。 請注意,如果將此對象與null對象一起使用,則會導致NPE,這可能進一步表明NPE正常。

你可以這樣做

int width, height;

public Rectangle(int width, int height) {
    this.width = width;
    this.height = height;
}

public Rectangle(Rectangle source) {
   if(source != null) {
      width = source.width;
      height = source.height;
   }
}

暫無
暫無

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

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