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

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

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

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

Q&A

解決済

2回答

2142閲覧

ローカル変数のスコープについて

kazuhi

総合スコア15

Java

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

0グッド

0クリップ

投稿2016/04/27 02:05

###前提・実現したいこと
クラスメソッドローカル変数のスコープについてご教示ください。

クラスメソッドの中でJButton を生成しアクションイベントを定義しました。
このアクションイベントの中でクラスメソッド内のローカル変数にアクセスできます。また、メソッドが終了した後にボタンクリックによるアクションイベントが実行された場合でも値が保存されているように見えます。

メソッド内で定義したローカル変数なので、メソッドが終了してしまえばこのローカル変数もスコープ外となと思うのですが。
そもそもこのコーディングは間違えでしょうか?
また、ローカル変数へfinalを付けた場合との違いは有るのでしょうか?

当サイト初心者で他に同様の投稿があるか検索できませんでした。
また、JAVAにも精通していません。
申し訳ございませんがご教示の程よろしくお願いいたします。

###ソースコード
public class SSample11_1{

static JFrame frame; static JPanel p; static Test1XX[] t1 = new Test1XX[10]; public static void main(String args[]){ SSample11_1 ss = new SSample11_1(); } SSample11_1() { frame = new JFrame("タイトル"); frame.setBounds(100, 100, 300, 250); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Container contentPane = frame.getContentPane(); p = new JPanel(); p.setLayout(null); contentPane.add(p, BorderLayout.CENTER); frame.setVisible(true); for(int i = 0; i<10 ; i++){ t1[i] = new Test1XX(); } for(int i = 0; i<10 ; i++){ t1[i].test1xx1(i); t1[i].test1xx2(9-i); } } class Test1XX { private JButton btn; int _iii; public void test1xx1(int i) { final int _i = i; int _ii = i; System.out.println("_i=" + Integer.toString(_i)+"_ii=" + Integer.toString(_ii)); btn = new JButton(String.valueOf(i)); btn.setBounds(0, i*22, 100, 20); SSample11_1.p.add(btn); btn.setVisible(true); btn.repaint(); btn.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent event){ JLabel msg = new JLabel("クリックされました - > "+String.valueOf(_i)+" : "+String.valueOf(_ii)); JOptionPane.showMessageDialog(frame, msg); } }); } public void test1xx2(int i) { final int _i = i; _iii=i; System.out.println("_i=" + Integer.toString(_i)+"_iii=" + Integer.toString(_iii)); } }

}

###補足情報(言語/FW/ツール等のバージョンなど)
JDK1.8で確認しました。

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

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

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

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

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

guest

回答2

0

ベストアンサー

インナークラスからfinalなローカル変数が参照できるのは、実はインナークラスの生成時に、裏でコピーしているからです。コピーしても矛盾が生じないfinal変数だけを参照できるようになっています。

内部クラスからアクセス可能なローカル変数が final でなければならない理由

投稿2016/04/27 02:41

maisumakun

総合スコア145123

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

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

kazuhi

2016/04/27 02:54

ご回答ありがとうございます。 内部クラスからローカル変数にアクセスするには、 final でなければならない事は一応承知しています。 私のソースの場合「クラスメソッドの中でJButton を生成しアクションイベントを定義していますが」、これは内部クラスという事になるのでしょうか? そうであったとすると、一緒にローカル変数として定義しているfinalでない変数にもアクセスできてしまいますがなぜでしょうか? public void test1xx1(int i) { final int _i = i; int _ii = i; メソッドで定義した変数に public void actionPerformed(ActionEvent event){ JLabel msg = new JLabel("クリックされました - > "+String.valueOf(_i)+" : "+String.valueOf(_ii)); アクションイベント内で参照できてしまいます。また、値も保存されています。 よろしくお願いいたします。
kazuhi

2016/04/27 10:02

ありがとうございました。 確かにjava1.4.x等の古いバージョンで試すとコンパイルエラーになりました。 しかし、これは紛らわしいです。ローカル変数の有効なスコープとは違った意味になってしまいますよね。ローカル変数の宣言には注意します。 final についてもご教示ありがとうございました。 finalで宣言された変数は、同一スコープ内で、内部クラスが生成される毎にそのクラス内にコピー領域が確保されるという事ですね。本来スコープ外になると領域が消滅したはずの実態のコピーが内部クラスには残っているという事とですね。 finalについても、なんとなく理解していましたが、仕組みを考えて注意して使えます。
guest

0

クラスメソッドの中でJButton を生成しアクションイベントを定義しました。

上記が以下を指しているのであれば、誤った理解があるようです。

java

1 class Test1XX { 2 private JButton btn; 3

上記だと、btnはクラス「Test1XX」に定義されたメンバ変数となります。
そのため、Test1XXのインスタンスが保持されている間、btnのインスタンスも保持されていることとなります。

クラス「SSample11_1」のメンバ変数として「static Test1XX[] t1 = new Test1XX[10];」のようにクラス「Test1XX」のインスタンス(配列)をメンバ変数として保持しているため、結果的にクラス「SSample11_1」が終了するまでクラス「Test1XX」のインスタンスが保持されており、btnのインスタンスも保持されていることとなります。


また、ローカル変数へfinalを付けた場合との違いは有るのでしょうか?

「final」は変数のスコープとは直接関係ありません。


Javaの学習をどのように行っているか不明ですが、何か書籍を1冊読み込み基礎的な部分の理解を深めることをお勧めします。

  • クラスとは
  • インスタンスとは
  • クラスとインスタンスの違い
  • 文法(public/private/protected, final, static)
  • メソッドとは
  • メンバとは

など。

特にインスタンスや変数のスコープに関しては、実際の業務でもわかりづらい障害(不具合)になることも多いです。やってみて初めて腑に落ちる部分もあるかと思いますので、がんばって学習してみてください。

投稿2016/04/27 02:29

takyafumin

総合スコア2335

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

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

kazuhi

2016/04/27 02:35

早速、ご回答ありがとうございます。 少し、質問の仕方が悪かったと思います。 確認したかったのはメソッド内のローカル変数についてです。 public void test1xx1(int i) { final int _i = i; int _ii = i; ボタンや、クラスはインスタンス化されているので消滅していない事は理解できます。 上記のローカル変数は関数が終了してしまえば消滅すると思いますが。。。
takyafumin

2016/04/27 04:30

質問の意図を取り違えていました。すみません。 別途maisumakunさまからの回答にあるように、finalな変数がインナークラス(や無名クラス)に暗黙的にコピーされるようですね。 勉強になりました。 回答欄の以下を撤回します。 --- >> また、ローカル変数へfinalを付けた場合との違いは有るのでしょうか? > 「final」は変数のスコープとは直接関係ありません。
kazuhi

2016/04/27 10:04

ご対応ありがとうございました。 考えるきっかけになりました。 言語が違うと仕組みも異なり大変です。もっと勉強します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問