[英]Multiple Constructors with no default parameter value for some parameters
如果您需要創建多個構造函數,直接的解決方案是鏈接構造函數。 一個構造函數使用一些默認值調用另一個構造函數。 但是如果沒有默認值怎么辦?
例如具有以下三個構造函數的 class :
public MyClass(Person person, SomeEnum enum1) // constructor 1
{
if (person== null)
{
throw new IllegalArgumentException("person cannot be null.");
}
if (enum1== null)
{
throw new IllegalArgumentException("enum1 cannot be null.");
}
this.person= person;
this.enum1 = enum1;
}
public MyClass(Person person) // constructor 2
{
if (person== null)
{
throw new IllegalArgumentException("person cannot be null.");
}
this.person= person;
}
public MyClass(SomeEnum enum1) // constructor 3
{
if (enum1== null)
{
throw new IllegalArgumentException("enum1 cannot be null.");
}
this.enum1 = enum1;
}
我不想在多個構造函數中驗證相同的字段,所以我會嘗試讓構造函數 2和3調用構造函數 1 :
public MyClass(Person person, SomeEnum enum1) // constructor 1
{
if (person== null)
{
throw new IllegalArgumentException("person cannot be null.");
}
if (enum1== null)
{
throw new IllegalArgumentException("enum1 cannot be null.");
}
this.person= person;
this.enum1 = enum1;
}
public MyClass(Person person) // constructor 2
{
this(prerson, SomeEnum.NO_VALUE);
}
public MyClass(SomeEnum enum1) // constructor 3
{
this(?, enum1);
}
因此,假設我們在SomeEnum中有一些默認值,但是對於構造函數 3 ,我沒有Person的默認值。 我可以更改調用鏈並使構造函數 1 和 2 調用構造函數 3,然后自己驗證和設置 Person,但我不希望 Person 驗證在兩個地方。
我也不喜歡創建一些擴展Person並使用它的NotPerson object 的想法。 建造者模式也不適合我。 此外,驗證可能比僅檢查 null 更復雜。
如果您的問題主要是重復檢查,那么Project Lombok可以輕松解決這個問題。 它將自動生成等效代碼。 它默認使用 NullPointerException,但如果您願意,可以配置為使用 IllegalArgumentException。
public MyClass(@NonNull Person person, @NonNull SomeEnum enum1) {
this.person = person;
this.enum1 = enum1;
}
public MyClass(@NonNull Person person) {
this.person = person;
}
public MyClass(@NonNull SomeEnum enum1) {
this.enum1 = enum1;
}
一種方法是編寫私有 static 驗證方法。 使用它們的緊湊方式如下所示:
public MyClass(Person person, SomeEnum enum1) {
this.person = validatePerson(person);
this.enum1 = validateSomeEnum(enum1);
}
public MyClass(Person person) {
this.person = validatePerson(person);
}
public MyClass(SomeEnum enum1) {
this.enum1 = validateSomeEnum(enum1);
}
private static Person validatePerson(Person person) {
if (person == null) {
throw new IllegalArgumentException("person cannot be null.");
}
return person;
}
private static SomeEnum validateSomeEnum(SomeEnum enum1) {
if (enum1 == null) {
throw new IllegalArgumentException("enum1 cannot be null.");
}
return enum1;
}
用途
MyClass myClass = new MyClass(person, enum1);
MyClass myClass = new MyClass(person);
MyClass myClass = new MyClass(enum1);
您也可以使用 static 構造方法來做到這一點,如果存在歧義,有助於澄清 arguments,方法是不同地命名 static 方法:
public static MyClass of(Person person, SomeEnum enum1) {
validatePerson(person);
validateSomeEnum(enum1);
return new MyClass(person, enum1);
}
public static MyClass of(Person person) {
validatePerson(person);
return new MyClass(person, null);
}
public static MyClass of(SomeEnum enum1) {
validateSomeEnum(enum1);
return new MyClass(null, enum1);
}
private static void validatePerson(Person person) {
if (person == null) {
throw new IllegalArgumentException("person cannot be null.");
}
}
private static void validateSomeEnum(SomeEnum enum1) {
if (enum1 == null) {
throw new IllegalArgumentException("enum1 cannot be null.");
}
}
private MyClass(Person person, SomeEnum enum1) {
this.person = person;
this.enum1 = enum1;
}
用途
MyClass myClass = MyClass.of(person, enum1);
MyClass myClass = MyClass.of(person);
MyClass myClass = MyClass.of(enum1);
另一種選擇是構建器模式,如果有許多可選屬性,則特別有用:
public static final class Builder {
private Person person;
private SomeEnum enum1;
public Builder withPerson(Person person) {
if (person == null) {
throw new IllegalArgumentException("person cannot be null.");
}
this.person = person;
return this;
}
public Builder withSomeEnum(SomeEnum enum1) {
if (enum1 == null) {
throw new IllegalArgumentException("enum1 cannot be null.");
}
this.enum1 = enum1;
return this;
}
public MyClass create() {
if (this.person == null && this.enum1 == null) {
throw new IllegalArgumentException("One of person or enum1 is required.");
}
return new MyClass(this.person, this.enum1);
}
}
private MyClass(Person person, SomeEnum enum1) {
this.person = person;
this.enum1 = enum1;
}
用途
MyClass myClass = new MyClass.Builder()
.withPerson(person)
.withSomeEnum(enum1)
.create();
MyClass myClass = new MyClass.Builder()
.withPerson(person)
.create();
MyClass myClass = new MyClass.Builder()
.withSomeEnum(enum1)
.create();
另一種解決方案是更好地重新排列鏈調用:
public MyClass(Person person, SomeEnum enum1) // constructor 1
{
this(enum1);
if (person== null)
{
throw new IllegalArgumentException("person cannot be null.");
}
this.person= person;
}
public MyClass(Person person) // constructor 2
{
this(person, SomeEnum.NoValue);
}
public MyClass(SomeEnum enum1) // constructor 3
{
if (enum1== null)
{
throw new IllegalArgumentException("enum1 cannot be null.");
}
this.enum1 = enum1;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.