2012-04-17 8 views
1
import javax.swing.*; 
import javax.swing.event.*; 

public class NewGUIStuff{ 
    public static void main(String args[]){ 
     NewGUIStuff gui = new NewGUIStuff(); 
     gui.go(); 
    } 

    class handlesListListeners implements ListSelectionListener{ 
     public void valueChanged(ListSelectionEvent lse){ 
      list.setVisibleRowCount(4); 
     } 
    } 
    public void valueChanged(ListSelectionEvent lse){ 

    } 
    public void go(){ 
     JFrame frame = new JFrame(); 
     JPanel panel = new JPanel(); 
     JList list; 

     String[] aList = {"alpha","beta","gamma","delta","epsilon","zeta","eta","theta"}; 
     list = new JList(aList); 
     list.addListSelectionListener(new handlesListListeners()); 
     JScrollPane scroller = new JScrollPane(list); 
     scroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); 
     scroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 

     frame.setContentPane(scroller); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setSize(300,300); 
     frame.setVisible(true); 
    } 
} 

だからここに私の質問は、なぜ内部クラスhandlesListListenersは私がNewGUIStuff外側のクラスで行われたlistオブジェクトを見ることができませんか?私の内部クラスが外部クラスオブジェクトを見ることができないのはなぜですか?内部クラスは、その外側のクラス変数やオブジェクトを見ることができれば

+1

同じパッケージに入っていますか? –

+0

これはすべて1つのファイルです。 –

答えて

2

非静的な内部クラス外部クラスにインスタンス変数とそれらのローカル変数を参照することができ、それらは(匿名内部クラスの場合)final宣言された場合、彼らは(クロージャを考える)の周りに囲まれました。これらの非静的な内部クラスは、コンパイラによって挿入された外側のthisへの暗黙の参照を持ち、それが外部クラスのメンバ変数をどのように見ているかです。匿名クラスを囲む最後のローカル変数は、コンパイラが生成するコンストラクタに暗黙的に渡され、内部クラスの最終メンバフィールドに格納されます。

あなたのケースでは、あなたの内部クラスが全く知らない、まったく異なる語彙コンテキストで定義されたローカル変数を見たいと思うのが分かります。これを外側のクラスメンバ変数に変換すると、内部クラスにその変数が表示されます。

+0

これらの答えはどれほどのものかわかりましたが、これが私を最も助けました。あなたは私がスコープの点で予想していたことについて混乱していたところを見ました。そして、私はあなたにそれを感謝します。 –

2

答えは「あなたの内面のクラスは外の階級を見ることができます」というのはあなたの問題ではない。

あなたの問題は、NewGUIStuffクラスに、内部クラスのメンバーフィールドが表示されないことです。宣言したlist変数は、goメソッドのローカル変数です。

public class NewGUIStuff { 
    JList list; //this is a member field 

    ... 

    public void go() { 
     ... 
     JList list; //this is a local variable 
     ... 
    } 
} 
+0

ここで私はいくつかの混乱がありました。もしgo()メソッド中に新しいオブジェクトを作成していたら、オブジェクトはそのメソッド内で作成されたので、内部クラスはそれを見てはいけませんか? –

+0

私はここであなたが言っているものを得るかもしれないと思います。だから、goメソッドが他のすべてを終了するとき、リスナーはまだ存在するが、 'go()'メソッドはスタックになくなり、 'list'への参照はなくなります。 –

+0

はい。 goメソッドのリストへの参照はなくなりました。もっと重要なことに、 'list'変数は内部クラスには決して見えませんでした。受け入れた答えは、技術的な詳細を説明しています。 –

2

リストオブジェクトは、NewGUIStuffクラスのスコープではなく、go()メソッドのスコープの内側にあるためです。リストオブジェクトは、同じメソッドの中でしか見ることができません。

+0

ありがとう、誰かが私が混乱していたところでもう少し詳しく説明しましたが、あなたの答えに感謝します。 –

1

list変数は、go()のローカル変数です。可視にしたい場合は、NewGUIStuffというインスタンスフィールドにする必要があります。このような何か:

public class NewGUIStuff { 

    private JList list = new JList(); // Member of outer class so in scope from handlesListListeners 

    public static void main(String args[]) { 
     NewGUIStuff gui = new NewGUIStuff(); 
     gui.go(); 
    } 

    class handlesListListeners implements ListSelectionListener { 

     public void valueChanged(ListSelectionEvent lse) { 
      list.setVisibleRowCount(4); 
     } 
    } 
} 
+0

これは、誰もが正しく言っていることを読んでいれば、可変スコープのコンテキストを十分に理解できなかった場合です。 –

1

listgo()関数内のローカル変数であるためです。 handlesListListenersクラスの対象外です。

listが外部クラスのインスタンス変数だった場合、内部クラスはそれを見ることができます。

void go() { 
    final JList list = ... 
    list.addListSelectionListener(new ListSelectionListener() { 
     public void valueChanged(ListSelectionEvent event) { 
      // list is now in scope 
      list.setVisibleRowCount(4); 
     } 
    }); 
} 

注それは、この中で使用されている場合list最終であると宣言しなければならないということ。また、あなたはlistがスコープ内に今あることを意味している、あまりにも、go()関数にローカルあなたの内部クラスを作ることができます方法。

+0

これは一種のクールで理にかなっています。ありがとう。 –

+1

匿名の内部クラスは非常に便利です。彼らは一般的に、GUIを構築するときに行く良い方法です。 –

関連する問題