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
?因为其他构造函数调用必须是我的构造函数中的第一个语句。
答案 0 :(得分:2)
您可以引入一个私有静态方法,通过null
检查返回相关值以抛出IllegalArgumentException
(在这种情况下是宽度,因为它是同一对象上的第一个参数)。
例如:
public class Rectangle {
private int width, height;
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
public Rectangle(Rectangle rectangle) {
this(getWidth(rectangle), rectangle.height);
}
private static int getWidth(Rectangle rectangle) {
if (rectangle == null) {
throw new IllegalArgumentException("null value");
}
return rectangle.width;
}
}
反思上述问题的评论,为什么不NullPointerException
?
这个问题:IllegalArgumentException or NullPointerException for a null parameter?有一些很好的讨论要点。但我倾向于同意“有效Java”的观点,NullPointerException
应该优先考虑answer中提到的那个问题。
“可以说,所有错误的方法调用都归结为非法 参数或非法状态,但标准使用其他例外 对于某些非法论点和国家。如果来电者通过 在禁止空值的某些参数中为null, 约定规定抛出NullPointerException而不是 抛出:IllegalArgumentException“。
答案 1 :(得分:1)
你可以使用java.lang.Objects,但它会抛出NullPointerException(带有你提供的消息)而不是IllegalArgumentException:
public class Rectangle {
private int width, height;
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
public Rectangle(Rectangle rectangle) {
this(Objects.requiresNotNull(rectangle, "rectangle was null").getWidth(), getHeight(rectangle));
}
...
}
如果您愿意,也可以将宽度和高度设为最终。
答案 2 :(得分:0)
如果你打开复制构造函数的替代品,那么复制静态工厂 - 请参阅Josh Bloch的 Effective Java ,第2版,项目11,第61页 - 会为您带来更大的灵活性:
public final class Rectangle {
private final int width
private final int height;
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
public static Rectangle newInstance(Rectangle source) {// <-- copy static factory
if (source == null) {
throw new IllegalArgumentException("null source");
}
return new Rectangle(source.width, source.height);
}
}
可以说,抛出NullPointerException
比投掷IllegalArgumentException
更具惯用性。
答案 3 :(得分:0)
如果你的代码库中某处有这个方法:
IllegalArgumentException
您可以使用它从构造函数中抛出public class Rectangle {
int width, height;
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
public Rectangle(Rectangle source) {
this(getIfNotNull(source, s -> s.width), source.height);
}
}
:
IllegalArgumentException
免责声明:只需抛出一个NullPointerException
就可以了所有这一点,这比NullPointerException
更少惯用。一般来说,如果某个不可为空的参数为null
,则抛出position: relative
是一种好习惯。在尝试取消引用该参数时,您的原始代码已经这样做了。
答案 4 :(得分:0)
可能最简单的解决方法是不要让构造函数调用另一个构造函数。没有任何优势,除非您正在进行课堂作业,并告知您必须这样做:
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
public Rectangle(Rectangle rectangle) {
if (rectangle == null) {
throw new IllegalArgumentException(...);
}
this.width = rectangle.width;
this.height = rectangle.height;
}
当然,您现在拥有重复的代码,但将其提取到两个构造函数使用的新私有方法中非常简单。
对于我而言,这似乎比发明一种将空检查机制成this(...)
的方式更为直接,正如其他几个答案所做的那样。