2011-12-29 7 views
0

私は最近JOGLで作業を始めました。そこでベクタークラスを作成しました。このクラスの中で、私はその線を使った。プロパティを呼び出すまでJavaを待機させる?

public Vector unit=new Vector(x/length,y/length,z/length); 

単位ベクトルを見つける。もちろん、これによってスタックオーバーフローが発生します。これを実行する前にユニットが呼び出されるまでJavaが待つようにする方法はありますか、ユニットをメソッドにしなければなりませんか?

答えて

1

私は単位ベクトルを計算し、それ自身の単位ベクトルを自身に設定する第2のコンストラクタを個人的に作成します。 Ernestが提案するように、理想的にはプライベートな値とgetメソッドを使用する必要があります。その理由は、そうでなければ、他のクラスがオブジェクトの1つにアクセスできる場合にx、y、zなどの値を単純に上書きすることができるからです。 Javaには、純粋なデータストレージに最終クラスを使用する伝統があります。たとえば、Stringクラスを参照してください。既存のStringを変更することはできません。新しいStringのみを作成してください。作成後、Stringは同じままです。あなたの目的のためにはそれほど重要ではないかもしれませんが、異なるコンテキストでは、あなたのクラスがヒントを持っていない人によって使用されている場合は、アプリケーションが誤動作する可能性があります。場合によってはセキュリティ上のリスクでもあります。

これを無視して直接変数にアクセスして、あまり乱雑なコードや小さなパフォーマンスを楽しむことができます。しかし、私はまだ問題が将来のために何であるかを知ることを提案するでしょう。

とにかく、以下は、単位ベクトルの問題を解決するためのマイナスのゲッターメソッドです。

import java.lang.Math; 

class Vector{ 
    public double x,y,z,length; 
    public Vector unit; 

    public static void main(String[]s){ 
     new Vector(5,5,5); 

    } 

    public Vector(double x, double y, double z){ 
     this.length = Math.sqrt(x*x + y*y + z*z); 

     this.x=x; 
     this.y=y; 
     this.z=z; 

     this.unit = new Vector(x/length, y/length, z/length, true); 
    } 

    private Vector(double x, double y, double z, boolean isUnitVector){ 
     // Temp variable for calculating the length 
     double length = Math.sqrt(x*x + y*y + z*z); 

     if (isUnitVector){ 
      this.length = 1; 

      this.x=x/length; 
      this.y=y/length; 
      this.z=z/length; 

      this.unit = this; 
     }else{ 
      this.length = Math.sqrt(x*x + y*y + z*z); 

      this.x=x; 
      this.y=y; 
      this.z=z; 

      this.unit = new Vector(x/length, y/length, z/length, true); 
     } 

    } 

} 

boolean引数の後に続くコンストラクタ間のコードの重複は完全に満足していません。実際には、ファクトリクラスVectorFactoryを1つの静的メソッドで作成します。その唯一の仕事はVectorオブジェクトを作成することです。あるいは、Javaの独自のjavax.vecmath.Vector3dとそれに関連するクラスを使用することもできます。

+0

説明をお寄せいただきありがとうございます。 – SDuke

1

はい、これは簡単ですが、デザインを少し修正する必要があります。最も重要なのは、すべてのメンバ変数のほとんどの場合と同様に、unitプライベートである必要があり、すべてのアクセスはgetUnit()という名前のメソッドを使用する必要があります。 、2つの異なるスレッドが同じ時期にgetUnit()を呼び出す場合は、すべての問題を回避しますように

public synchronized Vector getUnit() { 
    if (unit == null) 
     unit = new Vector(x/length,y/length,z/length); 
    return unit; 
} 

私はこの方法​​を作りました:その後、あなたは単にunitが初期化されているかどうかをチェックするためにgetUnit()を書きますunitはまだ初期化されていません。

+0

ありがとうございます。私が公開したのは、 'Vector.getX()'の代わりに 'Vector.unit'や' Vector.x'だけで楽しんだからです。適切な構文エチケットの他に、パブリックではなくプライベートでなければならない大きな理由はありますか? – SDuke

+0

変数を直接アクセスするのではなく、クライアントがメソッドを使用するように非公開にします。変数の初期化を遅らせることができるようにメソッドを使用します。名前をもっと短くしたい場合は 'unit()'と名付けることができます。 –

+0

私はそれを覚えています、説明をありがとうございます。 – SDuke

0

単位ベクトルであるかどうかを判断するコンストラクタを提案します。単位ベクトルの場合、unitはそれ自身を指します。これは、コンストラクタの再帰を中断します。 丸め誤差のため、lengthが正確に1.0ではない数字だけが唯一の問題です。

public class Vector { 
    public double x, y, z; 
    public Vector unit; 

    public Vector(double x, double y, double z){ 
     this.x = x; 
     this.y = y; 
     this.z = z; 
     double length = calcLength(x, y, z); 
     if(length == 1.0) // perhaps add a little fuzz factor. 
      this.unit = this; 
     else 
      this.unit = new Vector(x/length, y/length, z/length); 
    } 
} 
+0

毛羽立ちが最も確実に必要です。あなたのコードのものは、ループが繰り返されると長さが1に収束するということです。 if文の真の節が20回の再帰の後にとられるほど速く収束するかもしれません。つまり、ハードエラーは発生しませんが、パフォーマンスは低下します。私は実験をしていませんが、それは気をつけるべきことです! – nitro2k01

+0

今私はそれを試してみましたが、実際には問題ではないようです。私はかなりの極端な値を使っていても、余分な時間でさえ再帰することができませんでした。これはおそらく問題ではないはずです。一度繰り返すとしても、その価値はすばやく収束すべきであり、それはパフォーマンスには関係ありません。 – nitro2k01