나는 최근 Joshua Bloch의 Effective Java를 읽기 시작했습니다. 빌더 패턴 [책의 항목 2]에 대한 아이디어가 정말 흥미로 웠습니다. 내 프로젝트에서 구현하려고 시도했지만 컴파일 오류가 발생했습니다. 본질적으로 내가하려고했던 것은 다음과 같습니다.
여러 속성이있는 클래스 및 해당 빌더 클래스 :
public class NutritionalFacts {
private int sodium;
private int fat;
private int carbo;
public class Builder {
private int sodium;
private int fat;
private int carbo;
public Builder(int s) {
this.sodium = s;
}
public Builder fat(int f) {
this.fat = f;
return this;
}
public Builder carbo(int c) {
this.carbo = c;
return this;
}
public NutritionalFacts build() {
return new NutritionalFacts(this);
}
}
private NutritionalFacts(Builder b) {
this.sodium = b.sodium;
this.fat = b.fat;
this.carbo = b.carbo;
}
}
위의 클래스를 사용하려고하는 클래스 :
public class Main {
public static void main(String args[]) {
NutritionalFacts n =
new NutritionalFacts.Builder(10).carbo(23).fat(1).build();
}
}
다음과 같은 컴파일러 오류가 발생합니다.
효과적인 java.BuilderPattern.NutritionalFacts.Builder를 포함하는 둘러싸는 인스턴스가 필요합니다 NutritionalFacts n = new NutritionalFacts.Builder (10) .carbo (23) .fat (1) .build ();
메시지의 의미를 이해하지 못합니다. 설명 해주십시오. 위 코드는 그의 책에서 Bloch가 제안한 예제와 유사합니다.
답변
빌더를 static
클래스로 만드십시오 . 그런 다음 작동합니다. 정적이 아닌 경우 소유 클래스의 인스턴스가 필요하며 인스턴스가 없어야하며 빌더없이 인스턴스를 작성하는 것도 금지되어야합니다.
public class NutritionFacts {
public static class Builder {
}
}
참조 : 중첩 클래스
답변
Builder 클래스를 정적으로 만들어야하고 필드를 최종으로 설정하고 해당 값을 가져 오기위한 getter가 있어야합니다. 해당 값에 세터를 제공하지 마십시오. 이런 식으로 수업은 불변이 될 것입니다.
public class NutritionalFacts {
private final int sodium;
private final int fat;
private final int carbo;
public int getSodium(){
return sodium;
}
public int getFat(){
return fat;
}
public int getCarbo(){
return carbo;
}
public static class Builder {
private int sodium;
private int fat;
private int carbo;
public Builder sodium(int s) {
this.sodium = s;
return this;
}
public Builder fat(int f) {
this.fat = f;
return this;
}
public Builder carbo(int c) {
this.carbo = c;
return this;
}
public NutritionalFacts build() {
return new NutritionalFacts(this);
}
}
private NutritionalFacts(Builder b) {
this.sodium = b.sodium;
this.fat = b.fat;
this.carbo = b.carbo;
}
}
이제 다음과 같이 속성을 설정할 수 있습니다.
NutritionalFacts n = new NutritionalFacts.Builder().sodium(10).carbo(15).
fat(5).build();
답변
정적이 아닌 클래스에 정적 방식으로 액세스하려고합니다. 로 변경 Builder
하면 static class Builder
작동합니다.
Builder
존재하는 인스턴스가 없으므로 사용 예제가 실패합니다 . 모든 실용적인 목적을위한 정적 클래스는 항상 인스턴스화됩니다. 정적으로 만들지 않으면 다음과 같이 말해야합니다.
Widget = new Widget.Builder(10).setparm1(1).setparm2(3).build();
Builder
매번 새로운 것을 만들어야하기 때문입니다.
답변
Intellij IDEA에서 내부 빌더를 생성하려면 다음 플러그인을 확인하십시오. https://github.com/analytically/innerbuilder
답변
Builder
내부 클래스를로 선언해야합니다 static
.
비 정적 내부 클래스 와 정적 내부 클래스에 대한 설명서를 참조하십시오 .
기본적으로 정적이 아닌 내부 클래스 인스턴스는 연결된 외부 클래스 인스턴스가 없으면 존재할 수 없습니다.
답변
일단 아이디어가 생기면 실제로는 롬복이 @Builder
훨씬 더 편리하다는 것을 알게 될 것 입니다.
@Builder
다음과 같은 코드로 클래스를 인스턴스화하는 데 필요한 코드를 자동으로 생성 할 수 있습니다.
Person.builder()
.name("Adam Savage")
.city("San Francisco")
.job("Mythbusters")
.job("Unchained Reaction")
.build();
답변
이것은 둘러싸 기 유형을 만들 수 없음을 의미합니다. 즉, 먼저 “부모”클래스의 인스턴스를 승인 한 다음이 인스턴스에서 중첩 된 클래스 인스턴스를 작성할 수 있습니다.
NutritionalFacts n = new NutritionalFacts()
Builder b = new n.Builder(10).carbo(23).fat(1).build();