1. ホーム
  2. java

[解決済み] なぜ無名クラスではfinal変数しかアクセスできないのですか?

2022-03-14 10:11:37

質問

  1. a はここでしかできないことです。 再割り当ての方法を教えてください。 a において onClick() をプライベートメンバーとして維持することなく、メソッドを使用できますか?

    private void f(Button b, final int a){
        b.addClickHandler(new ClickHandler() {
    
            @Override
            public void onClick(ClickEvent event) {
                int b = a*5;
    
            }
        });
    }
    
    
  2. を返すにはどうしたらいいのでしょうか? 5 * a クリックしたとき?という意味です。

    private void f(Button b, final int a){
        b.addClickHandler(new ClickHandler() {
    
            @Override
            public void onClick(ClickEvent event) {
                 int b = a*5;
                 return b; // but return type is void 
            }
        });
    }
    
    

どのように解決するのか?

コメントで指摘されているように、この一部はJava 8では無意味になります。 final は暗黙の了解とすることができる。ただし 事実上 final 変数は、匿名内部クラスやラムダ式で使用することができます。


基本的にはJavaの管理方法によるものです。 クロージャ .

匿名内部クラスのインスタンスを作成すると、そのクラス内で使用されるすべての変数に は、自動生成されるコンストラクタによってコピーされます。これにより、例えばC#コンパイラのように、コンパイラがローカル変数の論理状態を保持するために様々な追加の型を自動生成する必要がなくなります... (C#が匿名関数で変数をキャプチャするとき、それは本当に変数をキャプチャします。クロージャは、メソッドのメインボディから見える方法で変数を更新でき、その逆もまた可能です。)

値が匿名の内部クラスのインスタンスにコピーされたので、その変数がメソッドの残りの部分によって変更されると奇妙に見えるでしょう。 となる 異なる時間に取得されたコピーで作業していることになります)。同様に、無名の内部クラスで変更を加えた場合、開発者はその変更が内部メソッドのボディで見えることを期待するかもしれません。

値を一切変更できないので、そのような変更が目に見えるかどうかを心配する必要はないのです。メソッドと匿名の内部クラスが互いの変更を見ることができるようにする唯一の方法は、何らかの記述のミュータブル型を使用することです。これは包含するクラスそのものであったり、配列であったり、ミュータブルラッパータイプであったり、そんなものです。基本的には、あるメソッドと別のメソッドの間で通信を行うようなものです。 パラメータ に対する変更は、そのメソッドの呼び出し元には見えません。 参照先 パラメータによって見られる。

JavaとC#のクロージャをもっと詳しく比較したい方は 記事 があり、さらに踏み込んだ内容になっています。この回答では、Java側に焦点を当てたかったのです :)