質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

517閲覧

Java Stackの要素を配列にするとpeekした値がおかしい

Telart

総合スコア2

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2022/12/29 22:07

前提

JavaでStackを使ったundo処理を実装しようとしていたところ、上手くいかないため質問します。
int[]を要素とするStack<int[]> stackを定義し、0のみを要素に持つint[] arrayをpushします。
次に、int[] array1にpeekでstackの先頭の配列を代入します。
この時点で、stackの先頭には0のみを持つ配列があるはずです。

ここで、array1[0]の要素を1にすると、なぜかstackの先頭の配列の0番目も1に置き換わってしまいます。

原因を教えてほしいです。

実現したいこと

  • 配列を使ったStackで、peekで代入した値を書き換えても、元のstackの先頭の値は書き換わらないようにしたい。

該当のソースコード

Java

1import java.util.Stack; 2 3class Test1 { 4 static Stack<int[]> stack = new Stack<int[]>(); 5 public static void main(String[] args) { 6 int[] array = new int[2]; 7 array[0] = 0; 8 array[1] = 0; 9 10 stack.push(array); 11 int[] array1 = stack.peek(); 12 printArray(array1); 13 14 array1[0] = 1; 15 printArray(array); 16 int[] array2 = stack.peek(); 17 18 printArray(array1); 19 printArray(array2); 20 } 21 22 public static void printArray(int[] array) { 23 for (int i = 0; i < array.length; i++) { 24 System.out.printf("%2d" ,array[i]); 25 } 26 System.out.print("\n"); 27 } 28}

Java

1import java.util.Stack; 2 3class Test2 { 4 static Stack<Integer> stack = new Stack<Integer>(); 5 public static void main(String[] args) { 6 int num = 0; 7 8 stack.push(num); 9 int num1 = stack.peek(); 10 System.out.println(num1); 11 12 num1 = 1; 13 System.out.println(num); 14 int num2 = stack.peek(); 15 16 System.out.println(num1); 17 System.out.println(num2); 18 } 19}

実行結果

$ java Test1 0 0 1 0 1 0 1 0
$ java Test2 0 0 1 0

試したこと

Integer型を要素とするStackで同じようなプログラムを作っても、stackの先頭が置き換わることはありませんでした。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

配列はオブジェクトで、オブジェクト変数は参照です。参照先の "内容の" 変更は、同じオブジェクトを指す参照全てに影響します。

参照状態遷移図

int (等のプリミティブ)の場合は変数に直に値が入り stack に入るのは autoboxing されたオブジェクトであって参照のように共有状態にならない為、各変数を変更しても他に影響はありません。

プリミティブの場合の図

投稿2022/12/30 04:00

編集2022/12/30 17:41
jimbe

総合スコア12632

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Telart

2022/12/30 04:38

オブジェクト変数は参照であることが完全に抜け落ちてました。ありがとうございます。
guest

0

ベストアンサー

peek()の仕様を理解しよう。 https://docs.oracle.com/javase/jp/8/docs/api/java/util/Stack.html#peek--

このときオブジェクトはスタックから削除されません。

つまり、

java

1 int[] array1 = stack.peek(); 2... 3 int[] array2 = stack.peek();

は、どちらもStackの先頭のオブジェクトを取り出している。取り出してもオブジェクトはStackからは削除されない。つまりどちらも同じオブジェクト。

JavaでStackを使ったundo処理を実装しようとしていたところ

undo処理を実装したいのであれば、push/popが適切ではないかと。ついでに加えれば、pushするときは配列を複製しないとまたおかしなことになるでしょう。

java

1stack.push(Arrays.copyOf(array, array.length));

https://docs.oracle.com/javase/jp/8/docs/api/java/util/Arrays.html#copyOf-int:A-int-

投稿2022/12/30 02:05

shiketa

総合スコア3971

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Telart

2022/12/30 04:42

array1にStackの先頭の内容をコピーするイメージで使おうとしていたのですが、copyOfメソッドは知らなかったので参考になります。pushやpeekするときに配列をコピーして行うことで同じオブジェクトを参照するのを防げました。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問