web-dev-qa-db-ja.com

静的メソッドから新しいオブジェクトを返すのは安全ですか?

このようなクラスがあってもいいですか

public class Weapon {
    private string name;
    private int might;
    // etc...

    private Weapon(String name, int might) {
        this.name = name;
        this.might = might;
    }

    public static final Weapon Alondite = new Weapon("Alondite", 16);
    // 100++ weapon
}

次に、このようにプロジェクトのどこかで武器を呼び出しますWeapon.Alondite、これは静的なたびに新しいオブジェクトを作成します 方法 メンバーが呼ばれた?

または、オブジェクトを1回だけ作成するようにするには、このようにしますか

public class Weapon {
    private string name;
    private int might;
    // etc...

    private Weapon(String name, int might) {
        this.name = name;
        this.might = might;
    }

    private static Weapon mAlondite;
    public static Weapon Alondite() {
        //if (mAlondite == null) {
        //    mAlondite = new Weapon("Alondite", 16);
        //    return mAlondite;
        //} else {
        //    return mAlondite;
        //}

        // EDIT: as suggested by everyone
        if (mAlondite == null) {
            mAlondite = new Weapon("Alondite", 16);
        }
        return mAlondite;
    }
}
6
SIRS

いいえ、最初のコードスニペットは、参照するたびに新しい武器を作成しません。

投稿した2番目の例は、シングルトンパターンの例です。

最初の例の下部にあるコメントに基づいて、さまざまな武器のインスタンスが100以上あることを示しているようです。これはたくさんあります。同じ武器の複数のインスタンスが必要なわけではないのは当然です(理由はさまざまですが、例では単一性を示しているようです)。

別の種類の武器を作成する必要がある場合、あるいは100や1000を作成する必要がある場合にどうなるかを検討する必要があるかもしれません。毎回再コンパイルする必要はありません。そうしないと、クラス自体の目的が、武器自体ではなく、武器タイプのリストとして誤解される可能性があります。

あなたの例に基づくと、100種類以上の武器タイプは名前が異なるだけで、おそらく異なるようです。その場合、動作ではなくデータのみが異なるので、ファイルなどから読み取り、それらを検索する手段を提供することを検討する場合があります(リポジトリパターンと同様)。

public class WeaponLookup {

    private Map<String, Weapon> weapons = new HashMap<>();

    public WeaponLookup(Map<String, Weapon> weapons) { // loaded from file or something
        this.weapons = weapons;
    }

    public Weapon Lookup(String name) {
        return weapons.get(name);
    } 
}

あなたはあなたの武器が2つに限定されない多くの属性を持っているとコメントで述べました。これは、クラスにコンパイルされるのではなく、外部のコンパイルされていないデータファイルを使用する方に移行すると思います。

あなたはこのようなものを比較することができます

{
    "weapons" : [
        {
            "name" : "Almonite",
            "might" : 16,
            "def-bonus" : 7,
            "spd-bonus" : 9
        },
        {
            "name" : "Alphite",
            "might" : 22,
            "def-bonus" : 2,
            "spd-bonus" : 3
        },
        {
            "name" : "Betite",
            "might" : 16,
            "def-bonus" : 11,
            "spd-bonus" : 4
        },
        {
            "name" : "Gammite",
            "might" : 12,
            "def-bonus" : 7,
            "spd-bonus" : 7
        },
        {
            "name" : "Deltite",
            "might" : 19,
            "def-bonus" : 6,
            "spd-bonus" : 5
        },
        {
            "name" : "Thetite",
            "might" : 11,
            "def-bonus" : 2,
            "spd-bonus" : 11
        }
    ]
}

のようなものに

public static final Weapon Almonite = new Weapon("Almonite", 16, 7, 9);
public static final Weapon Alphite = new Weapon("Alphite", 22, 2, 3);
public static final Weapon Betite = new Weapon("Betite", 16, 11, 4);
public static final Weapon Gammite = new Weapon("Gammite", 12, 7, 7);
public static final Weapon Deltite = new Weapon("Deltite", 19, 6, 5);
public static final Weapon Thetite = new Weapon("Thetite", 11, 2, 11);

この例を見ると、これらの数値のどれがどのフィールドに属しているかがわかりますか。 Betiteの11はspd-bonusまたはdef-bonusですか?確かにわかりません。私はコンストラクターに行ってそれが何であるかを見ることができます(それはdef-bonusです)が、私は本当にそれをしたくありません。 100以上になるとすれば、これは長い

public static final Weapon Almonite = new Weapon("Almonite", 16, 7, 9);
public static final Weapon Alphite = new Weapon("Alphite", 22, 2, 3);
public static final Weapon Betite = new Weapon("Betite", 16, 11, 4);
public static final Weapon Gammite = new Weapon("Gammite", 12, 7, 7);
public static final Weapon Deltite = new Weapon("Deltite", 19, 6, 5);
public static final Weapon Thetite = new Weapon("Thetite", 11, 2, 11);
public static final Weapon Almonite = new Weapon("Almonite", 16, 7, 9);
public static final Weapon Alphite = new Weapon("Alphite", 22, 2, 3);
public static final Weapon Betite = new Weapon("Betite", 16, 11, 4);
public static final Weapon Gammite = new Weapon("Gammite", 12, 7, 7);
public static final Weapon Almonite = new Weapon("Almonite", 16, 7, 9);
public static final Weapon Alphite = new Weapon("Alphite", 22, 2, 3);
public static final Weapon Betite = new Weapon("Betite", 16, 11, 4);
public static final Weapon Gammite = new Weapon("Gammite", 12, 7, 7);
public static final Weapon Deltite = new Weapon("Deltite", 19, 6, 5);
public static final Weapon Thetite = new Weapon("Thetite", 11, 2, 11);
public static final Weapon Almonite = new Weapon("Almonite", 16, 7, 9);
public static final Weapon Alphite = new Weapon("Alphite", 22, 2, 3);
public static final Weapon Betite = new Weapon("Betite", 16, 11, 4);
public static final Weapon Gammite = new Weapon("Gammite", 12, 7, 7);
public static final Weapon Almonite = new Weapon("Almonite", 16, 7, 9);
public static final Weapon Alphite = new Weapon("Alphite", 22, 2, 3);
public static final Weapon Betite = new Weapon("Betite", 16, 11, 4);
public static final Weapon Gammite = new Weapon("Gammite", 12, 7, 7);
public static final Weapon Deltite = new Weapon("Deltite", 19, 6, 5);
public static final Weapon Thetite = new Weapon("Thetite", 11, 2, 11);
public static final Weapon Almonite = new Weapon("Almonite", 16, 7, 9);
public static final Weapon Alphite = new Weapon("Alphite", 22, 2, 3);
public static final Weapon Betite = new Weapon("Betite", 16, 11, 4);
public static final Weapon Gammite = new Weapon("Gammite", 12, 7, 7);
public static final Weapon Almonite = new Weapon("Almonite", 16, 7, 9);
public static final Weapon Alphite = new Weapon("Alphite", 22, 2, 3);
public static final Weapon Betite = new Weapon("Betite", 16, 11, 4);
public static final Weapon Gammite = new Weapon("Gammite", 12, 7, 7);
public static final Weapon Deltite = new Weapon("Deltite", 19, 6, 5);
public static final Weapon Thetite = new Weapon("Thetite", 11, 2, 11);
public static final Weapon Almonite = new Weapon("Almonite", 16, 7, 9);
public static final Weapon Alphite = new Weapon("Alphite", 22, 2, 3);
public static final Weapon Betite = new Weapon("Betite", 16, 11, 4);
public static final Weapon Gammite = new Weapon("Gammite", 12, 7, 7);
public static final Weapon Almonite = new Weapon("Almonite", 16, 7, 9);
public static final Weapon Alphite = new Weapon("Alphite", 22, 2, 3);
public static final Weapon Betite = new Weapon("Betite", 16, 11, 4);
public static final Weapon Gammite = new Weapon("Gammite", 12, 7, 7);
public static final Weapon Deltite = new Weapon("Deltite", 19, 6, 5);
public static final Weapon Thetite = new Weapon("Thetite", 11, 2, 11);
public static final Weapon Almonite = new Weapon("Almonite", 16, 7, 9);
public static final Weapon Alphite = new Weapon("Alphite", 22, 2, 3);
public static final Weapon Betite = new Weapon("Betite", 16, 11, 4);
public static final Weapon Gammite = new Weapon("Gammite", 12, 7, 7);
public static final Weapon Almonite = new Weapon("Almonite", 16, 7, 9);
public static final Weapon Alphite = new Weapon("Alphite", 22, 2, 3);
public static final Weapon Betite = new Weapon("Betite", 16, 11, 4);
public static final Weapon Gammite = new Weapon("Gammite", 12, 7, 7);
public static final Weapon Deltite = new Weapon("Deltite", 19, 6, 5);
public static final Weapon Thetite = new Weapon("Thetite", 11, 2, 11);
public static final Weapon Almonite = new Weapon("Almonite", 16, 7, 9);
public static final Weapon Alphite = new Weapon("Alphite", 22, 2, 3);
public static final Weapon Betite = new Weapon("Betite", 16, 11, 4);
public static final Weapon Gammite = new Weapon("Gammite", 12, 7, 7);
public static final Weapon Almonite = new Weapon("Almonite", 16, 7, 9);
public static final Weapon Alphite = new Weapon("Alphite", 22, 2, 3);
public static final Weapon Betite = new Weapon("Betite", 16, 11, 4);
public static final Weapon Gammite = new Weapon("Gammite", 12, 7, 7);
public static final Weapon Deltite = new Weapon("Deltite", 19, 6, 5);
public static final Weapon Thetite = new Weapon("Thetite", 11, 2, 11);
public static final Weapon Almonite = new Weapon("Almonite", 16, 7, 9);
public static final Weapon Alphite = new Weapon("Alphite", 22, 2, 3);
public static final Weapon Betite = new Weapon("Betite", 16, 11, 4);
public static final Weapon Gammite = new Weapon("Gammite", 12, 7, 7);
public static final Weapon Almonite = new Weapon("Almonite", 16, 7, 9);
public static final Weapon Alphite = new Weapon("Alphite", 22, 2, 3);
public static final Weapon Betite = new Weapon("Betite", 16, 11, 4);
public static final Weapon Gammite = new Weapon("Gammite", 12, 7, 7);
public static final Weapon Deltite = new Weapon("Deltite", 19, 6, 5);
public static final Weapon Thetite = new Weapon("Thetite", 11, 2, 11);
public static final Weapon Almonite = new Weapon("Almonite", 16, 7, 9);
public static final Weapon Alphite = new Weapon("Alphite", 22, 2, 3);
public static final Weapon Betite = new Weapon("Betite", 16, 11, 4);
public static final Weapon Gammite = new Weapon("Gammite", 12, 7, 7);
public static final Weapon Almonite = new Weapon("Almonite", 16, 7, 9);
public static final Weapon Alphite = new Weapon("Alphite", 22, 2, 3);
public static final Weapon Betite = new Weapon("Betite", 16, 11, 4);
public static final Weapon Gammite = new Weapon("Gammite", 12, 7, 7);
public static final Weapon Deltite = new Weapon("Deltite", 19, 6, 5);
public static final Weapon Thetite = new Weapon("Thetite", 11, 2, 11);
public static final Weapon Almonite = new Weapon("Almonite", 16, 7, 9);
public static final Weapon Alphite = new Weapon("Alphite", 22, 2, 3);
public static final Weapon Betite = new Weapon("Betite", 16, 11, 4);
public static final Weapon Gammite = new Weapon("Gammite", 12, 7, 7);
public static final Weapon Almonite = new Weapon("Almonite", 16, 7, 9);
public static final Weapon Alphite = new Weapon("Alphite", 22, 2, 3);
public static final Weapon Betite = new Weapon("Betite", 16, 11, 4);
public static final Weapon Gammite = new Weapon("Gammite", 12, 7, 7);
public static final Weapon Deltite = new Weapon("Deltite", 19, 6, 5);
public static final Weapon Thetite = new Weapon("Thetite", 11, 2, 11);
public static final Weapon Almonite = new Weapon("Almonite", 16, 7, 9);
public static final Weapon Alphite = new Weapon("Alphite", 22, 2, 3);
public static final Weapon Betite = new Weapon("Betite", 16, 11, 4);
public static final Weapon Gammite = new Weapon("Gammite", 12, 7, 7);

機能に実際に影響しない変更を行うたびに、プログラムの新しいバージョンをリリースしますか?私はしません。私はむしろ、データファイルの最新バージョンをダウンロードする更新チェッカーのようなものを用意したいだけです。機能が変わることはありませんが、突然、何千もの武器を追加できます。または武器を取り除くことさえ。予想よりも強力すぎる武器を追加した場合、ファイルからエントリを簡単に削除できます。コードを再構築してテストし、クライアントがダウンロードできるようにするのではなく、.

11
Zymus
_public static final Weapon Alondite = new Weapon("Alondite", 16);
_

次に、このWeapon.Alonditeのように、プロジェクト内のどこかで武器を呼び出すと、静的メソッドが呼び出されるたびに新しいオブジェクトが作成されますか?

まあそれはしません。それは方法ではありません。これは、静的メモリに格納されるパブリックメンバー属性です。武器はこれによって一度だけ構築されます。これに関する唯一の「安全でない」ことは、それが事実上グローバルであることです。

2番目のコードリストは シングルトンパターン での試みです。これもグローバルを設定します。

真剣に、Weaponmain()で一度だけ作成し、それを必要とするものへの参照のコピーを渡してみませんか?

4
candied_orange

別の角度からこれに答えようと思います。さまざまな属性(および場合によっては動作)を持つ武器の特定のインスタンスを作成しようとしているようです。代わりに多態性を使って、代わりに

public abstract class Weapon {
  private string name;
  private int might;
  // etc...
  public abstract void attack();
}
public class Alondite extends Weapon {
  public Alondite(){
    super("Alondite", 16);
  }
  @Override
  public void attack(){
    //Swoosh
  }
}
public class Kryptonite extends Weapon {
  public Kryptonite(){
    super("Kryptonite", 100);
  }
  @Override
  public void attack(){
    //Boom
  }
}

とにかく、あなたの質問に答えるために、あなたの意図に応じて静的メソッドからインスタンスを返すことは完全に安全です。あなたの質問と他の皆の観察に基づいて、あなたは各武器の1つのインスタンスが必要であるように見え、ある種のシングルトンパターンを見ています。その場合、上記の私の答えから拡張して、コンストラクターをプライベートに変更し、2番目のサンプルと同様に見える静的なgetInstanceメソッドを作成します。あなたはこのようなものが欲しいでしょう:

public class Alondite extends Weapon {
  private static Alondite instance = new Alondite();
  public static Alondite getInstance(){return instance;}
  private Alondite(){
    super("Alondite", 16);
  }
  // etc...
}

静的メンバーから順番に取得されるgetInstanceを介してのみインスタンスを取得できるため、これにより、各武器の1つのインスタンスがどこにでも作成されます。

ところで、2つ目のサンプルを作成する方法には、スレッド化の危険があります。 2つのスレッドが両方とも(alondite == null)ブロック、どちらも武器の個別のインスタンスを作成します。これは、2つのスレッドが2つの異なるインスタンスを指していることを意味します。

1
Rey Pader