140

私は最近、Joshua Bloch の『Effective Java』を読み始めました。Builder パターン [本書の項目 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();
    }
}

次のコンパイラ エラーが発生します。

effectivejava.BuilderPattern.NutritionalFacts.Builder を含む外側のインスタンスが必要です NutritionalFacts n = new NutritionalFacts.Builder(10).carbo(23).fat(1).build();

メッセージの意味がわかりません。説明してください。上記のコードは、ブロッホが著書で提案した例に似ています。

4

11 に答える 11

178

ビルダーをstaticクラスにします。それはうまくいくでしょう。静的でない場合は、所有するクラスのインスタンスが必要になります。ポイントは、そのインスタンスを持たないことであり、ビルダーなしでインスタンスを作成することさえ禁止することです。

public class NutritionFacts {
    public static class Builder {
    }
}

参照:ネストされたクラス

于 2011-02-15T17:54:20.893 に答える
14

Intellij IDEA で内部ビルダーを生成するには、次のプラグインを確認してください: https://github.com/analytically/innerbuilder

于 2014-01-31T10:09:44.890 に答える
12

静的な方法で非静的クラスにアクセスしようとしています。に変更Builderするstatic class Builderと、動作するはずです。

Builderpresentのインスタンスがないため、指定した使用例は失敗します。すべての実用的な目的のための静的クラスは、常にインスタンス化されます。静的にしない場合は、次のように言う必要があります。

Widget = new Widget.Builder(10).setparm1(1).setparm2(3).build();

Builder毎回新しいものを構築する必要があるためです。

于 2011-02-15T17:54:25.417 に答える
8

Builder内部クラスを として宣言する必要がありますstatic

非静的内部クラス静的内部クラスの両方について、いくつかのドキュメントを参照してください。

基本的に、非静的内部クラスのインスタンスは、外部クラスのインスタンスが添付されていないと存在できません。

于 2011-02-15T17:53:29.137 に答える
4

これは、enclose タイプを作成できないことを意味します。これは、最初に「親」クラスのインスタンスを作成する必要があり、次にこのインスタンスからネストされたクラス インスタンスを作成できることを意味します。

NutritionalFacts n = new NutritionalFacts()

Builder b = new n.Builder(10).carbo(23).fat(1).build();

ネストされたクラス

于 2011-02-15T17:53:19.273 に答える
3

Builder クラスは静的である必要があります。それ以上のコードを実際にテストする時間は今のところありませんが、うまくいかない場合はお知らせください。もう一度調べます.

于 2011-02-15T17:53:29.067 に答える
0

ここですでに述べたように、クラスを作成する必要がありますstatic。ちょっとした追加-必要に応じて、静的なものを使用しない少し異なる方法があります。

このことを考慮。クラス内で型セッターのようなものを宣言してビルダーを実装し、withProperty(value)それ自体への参照を返すようにします。このアプローチでは、スレッドセーフで簡潔な単一のエレガントなクラスがあります。

このことを考慮:

public class DataObject {

    private String first;
    private String second;
    private String third;

    public String getFirst(){
       return first; 
    }

    public void setFirst(String first){
       this.first = first; 
    }

    ... 

    public DataObject withFirst(String first){
       this.first = first;
       return this; 
    }

    public DataObject withSecond(String second){
       this.second = second;
       return this; 
    }

    public DataObject withThird(String third){
       this.third = third;
       return this; 
    }
}


DataObject dataObject = new DataObject()
     .withFirst("first data")
     .withSecond("second data")
     .withThird("third data");

その他のJava Builderの例については、こちらをご覧ください。

于 2019-08-08T19:03:08.527 に答える