3

私はJavaのクラスとコンストラクターについて学んでいます。サンプルプログラムのコードをいじってみましたが、何が起こっているのか正確に理解できないようです。

このコードはコンパイルされません。これは私にとって理にかなっています。

class Line {
Point start;
Point end;

Line(final Point start, final Point end) {

    this.start = new Point(start);
    this.end = new Point(end);
    start = new Point(0.4, 0.4);

}...

Pointオブジェクトのコンストラクターを呼び出して、元の開始Pointオブジェクト参照を別のPointオブジェクトに割り当てようとしています。最後のキーワードはこれと矛盾しています。

ただし、Pointstartパラメーターからfinalキーワードを削除すると...

class Line {
Point start;
Point end;

Line(Point start, final Point end) {

    this.start = new Point(start);
    this.end = new Point(end);
    start = new Point(0.4, 0.4);

}

実際には参照を変更していないようです。Lineコンストラクターに渡されたPointオブジェクトは、元のオブジェクトを指しているように見え、Lineコンストラクターのコードによって変更されません。では、何が得られるのでしょうか?これは、参照される「開始」がLineコンストラクターのスコープ内でローカルであるという事実と関係がありますか?

4

5 に答える 5

5

Javaは参照渡しを使用せず、常に値渡しを使用します。実際、Javaの参照タイプは単なるポインターであり、たとえばC#の参照とまったく同じ意味を共有していません。

したがって、コンストラクターでこのステートメントを実行すると、次のようになります。

start = new Point(0.4, 0.4);

元のPoint受け渡し引数は変更されません。ただし、ローカル変数(パラメーターを意味する)はPoint、座標によって定義された新しい変数を指します0,4, 0,4

理解を深めるには、次の記事を読んでください。Javaは値渡しです、くそっ!

于 2012-11-18T23:36:20.987 に答える
0

その変数はコンストラクターに対してローカルです。したがって、新しい参照を割り当てることは、コンストラクターの外部には存在しないため、コンストラクターの外部では意味がありません。

この種の効果を実現する1つの方法は、それを別のオブジェクトにラップすることです。そして、可変ラッパーへの参照を渡します。

于 2012-11-18T23:36:35.673 に答える
0

実際には参照を変更していないようです

そのメソッド自体の内部でメソッドを呼び出すために使用するパラメーターの参照を変更することはできません。パラメータの値(オブジェクトへの参照)はメソッドパラメータにコピーされるため、同じオブジェクトへの2番目の参照があります。メソッド内では、2番目の参照のみを変更でき、元の参照を変更することはできません。実行できる唯一のことは、参照されるオブジェクトを変更することです。

于 2012-11-18T23:36:39.363 に答える
0

「start=new Point(0.4、0.4);」を実行すると、コンストラクターで受信した開始を参照していることになります。コンストラクターがそれをfinalとして定義しているため、変数に新しい値を割り当てることは違法です。

詳細は、javaが値渡しアプローチを使用しているため、finalを使用せずにコンストラクター内の値を変更しても、元の値(パラメーターとしてメソッドに渡した値)の値はそのままであるということです。同じ。

于 2012-11-18T23:38:28.493 に答える
0

「Line(Pointstart、final Point end){」からの初期化後に「this.start = new Point(start)」を実行して「start」を変更すると、「start」が指すヒープ上の実際のオブジェクトは置き換えられません。ただし、既存の領域とは別の領域のヒープに新しいPointオブジェクトを割り当て、既存のポインタ「start」(STACKのスカラータイプ)を変更して、新しく割り当てられたものを指すようにします。

コンストラクターは、Javaヒープにオブジェクトが割り当てられた後、Javaの新しい演算子によって呼び出される特殊な目的のメソッド(関数)です。したがって、メソッドが呼び出されると、スタックが割り当てられ、スカラー型(Javaではint、double、char ...などのプリミティブ型)とメソッド内のREFERENCEがスタック(ヒープではなく)に割り当てられます。ステートメントを「finalObjecto= new Object()」と書くと、メモリに2つのものが割り当てられます。
まず、Javaヒープ上の「newObject()」。(HEAP)
次に、「オブジェクトo」であるスタック内の上記へのポインター。(STACK)
あなたの場合、スカラータイプでjvmメモリ(STACK)でのみ読み取り可能な「finalObjecto」を上書きしようとしました。

class Line {
Point start;
Point end;

// On the first line "Line(Point start, Point end) {",
// two references and two actual Objects that references point to
// are already allocated in memory.  
// So you've allocated four things.
Line(Point start, final Point end) { // "start" initialized on stack as final
    this.start = new Point(start); // tried to modify final variable on stack.
    this.end = new Point(end);
    start = new Point(0.4, 0.4);

}
于 2012-11-19T00:30:39.847 に答える