[英]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.