0

座標クラスを作成したいのですが、このクラスをインスタンス化すると、6 つの隣接する座標が自動的に作成されますが、それを行っているときに常にスタックオーバーフローの問題が発生し、それを解決する良い方法がありませんでした。これが私の間違ったコードです。問題は簡単にわかります。コンストラクター自体に含まれています。だから私はどうすればこの問題を解決できるのだろうか

public class Coordinate {

    private final int x;
    private final int y;
    private final Coordinate[] periperal;

    /**
     * The default constructor for Coordinate class that
     * sets up the coordinate to the given integers.
     * 
     * @param x value of x coordinate
     * @param y value of y coordinate
     */

    public Coordinate(){
        final Coordinate adjacent1 = new Coordinate(x, y + 1);
        final Coordinate adjacent2 = new Coordinate(x, y - 1);
            final Coordinate adjacent3 = new Coordinate(x - 1, y + 1);
        final Coordinate adjacent4 = new Coordinate(x - 1, y);
        final Coordinate adjacent5 = new Coordinate(x + 1, y);
        final Coordinate adjacent6 = new Coordinate(x + 1, y - 1);
        Coordinate[] list = {adjacent1, adjacent1, adjacent1, adjacent1, adjacent1, adjacent1};
        periperal = list;
    } 

なぜ間違っているのかはわかっていますが、それを修正する方法はわかりません。誰でも私を助けることができますか?どうもありがとう。

4

5 に答える 5

2

コンストラクターの最初の行は、再帰的かつ無条件に別のインスタンスを作成します。実際には、これは自分自身を呼び出すメソッドです。

この再帰が永遠に続くのを止めるには、なんらかの条件が必要です (スタックがなくなるまで)。

(無制限の) 座標系全体ですべての座標のインスタンスを作成しても機能しません。隣人の座標を取得する必要がありますか? それらは、実際に必要になったときに後でその場で計算できると思います。

于 2013-01-23T07:45:45.250 に答える
1

@Thilo は、コードの何が問題なのかを説明しました (+1)。解決策を提案したい。Coordinate実際には、 の他の 6 つのインスタンスを保持する のインスタンスを作成したいと考えていますCoordinate。同じコンストラクターからコンストラクターを呼び出すことはできません。無限再帰が生成されます。

したがって、ここに解決策があります:

  1. 偽の引数を受け入れるプライベート コンストラクターを作成します (それと「実際の」コンストラクターを区別するためだけに)。「実際の」コンストラクターから呼び出します。これにより、無限再帰が防止されます。
  2. コンストラクタ パッケージを保護します。コンストラクターからコンストラクターを呼び出すコードを削除します。すべてのインスタンスを作成し、セカンダリ インスタンスをプライマリ インスタンスに設定するファクトリ (またはファクトリ メソッド) を作成します。
于 2013-01-23T07:51:46.490 に答える
0

あなたは間違ったことを間違っています。他の人が言ったように、あなたは無限の領域をカバーしています。これだけでなく、各座標を無限に (x,y) が (x,y+1) を作成し、それ自体に対して (x,y-1) を作成しています。最初の1つ。

これらの問題を防ぐには、領域を制限する必要があります (座標を作成するときは、minX、maxX、minY、maxY が必要で、座標が外側にあるかどうかをテストします。その場合は作成しません)。同じ座標の再帰的な作成を防ぐには、作成済みの場所に保存する必要があります。座標が必要な場合はそこを見て、見つからない場合は作成して覚えておいてください。このようにして、各座標は一度だけ作成されます。

より良い方法は、最初にボード全体の座標を作成し、それらを配列に格納することです ((x,y) は x*width+y に変換されるため、1D 配列を使用できます。そして、それらは接続を追加します。

しかし、それさえも必要ありません。必要に応じて、実際の座標を使用して近傍を計算できます。このようにして、使用されていない大量のメモリと引き換えに、より多くのコンピューティングを行うことができます (また、Java は小さなオブジェクトを非効率的に格納します。これは、多数の小さな長期間存続するオブジェクトに悪影響を及ぼし、それらを取得することは、再計算するよりもさらにコストがかかる可能性があります)。しかし、時期尚早の最適化はとにかく悪の根源です。したがって、最初に動作させ、遅すぎる場合にのみ高速にします。

別の状況は、無限の可能性がある (ただし、実際に使用されたものによって制限されるすべての実際のケースで) ボードが必要な場合です。その場合、怠惰なアプローチが必要であり、必要のないものを保存しないようにします。

于 2013-01-23T08:11:23.120 に答える
0

コンストラクターで隣接する座標を設定する代わりに、それを newInstance() という静的メソッドに移動し、コンストラクターをプライベートにします。

public class Coordinate {

    private final int x;
    private final int y;
    private Coordinate[] periperal;

    /**
     * The default constructor for Coordinate class that
     * sets up the coordinate to the given integers.
     * 
     * @param x value of x coordinate
     * @param y value of y coordinate
     */

    public static Coordinate newInstance(int x, int y){
        final Coordinate instance = new Coordinate(x, y);
        final Coordinate adjacent1 = new Coordinate(x, y + 1);
        final Coordinate adjacent2 = new Coordinate(x, y - 1);
        final Coordinate adjacent3 = new Coordinate(x - 1, y + 1);
        final Coordinate adjacent4 = new Coordinate(x - 1, y);
        final Coordinate adjacent5 = new Coordinate(x + 1, y);
        final Coordinate adjacent6 = new Coordinate(x + 1, y - 1);
        Coordinate[] list = {adjacent1, adjacent2, adjacent3, adjacent4, adjacent5, adjacent6};
        instance.setPeriperal(list);
        return instance;
    }

    private Coordinate(int x, int y) {
        this.x = x;
        this.y = y;
    }

    private void setPeriperal(Coordinate[] periperal) {
        this.periperal = periperal;
    }
} 
于 2013-01-23T07:58:39.670 に答える
0

別の解決策: コンストラクターで隣接する Coordinate オブジェクトを作成しないでください。最初のポイントを作成している場所にそれらを作成し、セッター メソッドを使用して隣接する座標を設定します。

于 2013-01-23T08:56:21.770 に答える