DJ Chateau
DJ Chateau

Reputation: 148

Why can't my inner class see my outer class object?

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);
    }
}

So my question here is if inner classes can see their outer classes variables and objects, why can't the inner-class handlesListListeners see the list object I made in NewGUIStuff outer class?

Upvotes: 1

Views: 726

Answers (5)

darrengorman
darrengorman

Reputation: 13114

Your list variable is local to the method go(). If you want it to be visible you need to make it an instance field of NewGUIStuff. Something like this:

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);
        }
    }
}

Upvotes: 1

Pavel Veller
Pavel Veller

Reputation: 6105

Non-static inner classes can see the outer class instance variables and those local variables they were enclosed around (think closures) if those were declared final (in case of anonymous inner classes). Those non-static inner classes have an implicit reference to the outer this inserted by the compiler and that's how they see the member variables of the outer class. The final local variables you enclose your anonymous class around will be implicitly passed into the a constructor that the compiler will generate for you and stored in the final member fields of the inner class itself.

In your case I see you expect to see a local variable defined in a whole different lexical context, the one your inner class has no knowledge about. Convert it into the outer class member variable and your inner class will see it.

Upvotes: 2

Cameron Skinner
Cameron Skinner

Reputation: 54446

It's because list is a local variable in the go() function. It is out of scope for the handlesListListeners class.

If list were an instance variable of the outer class then the inner class would be able to see it. Alternatively, you could make your inner class local to the go() function, too, which would mean that list is now in scope:

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

Note that list must be declared to be final if it is used in this way.

Upvotes: 1

Kevin Crowell
Kevin Crowell

Reputation: 10150

Because the list object is inside the scope of the go() method, not the scope of the NewGUIStuff class. The list object can only be "seen" inside the that same method.

Upvotes: 2

Tim Bender
Tim Bender

Reputation: 20442

The answer is, "Your inner class can see the outer class", that isn't your problem.

Your problem is that the NewGUIStuff class does not have any member fields for the inner class to see. The list variable that you declared is local to the go method.

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

    ...

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

Upvotes: 2

Related Questions