为什么自引用指针或按钮中的范围超出范围?

时间:2015-05-04 23:10:38

标签: java swing this state self-reference

我尝试使用带有State模式的Swing库生成动态画布。我的代码可以编译,但是当按下按钮时,控制台上会出现红色标记。

问题:我的自引用指针或保留字超出了按钮的范围。我希望能够在没有任何静态的情况下访问该类。

错误:线程中的异常" AWT-EventQueue-0" java.lang.Error:未解决的编译问题:     类型State中的方法handlePush(SP)不适用于参数(new ActionListener(){})

这是画布类。

public class SP extends JPanel{
private static final long serialVersionUID = 1L;

private State state = null; 

public static void main(String[] args){
    SwingUtilities.invokeLater(new Runnable(){
        public void run(){
            createAndShowCanvasGUI();
        }
    });
}
public SP(State state ){
    this.state = state;
    init();
}
public SP(){
    this(new BlackState());
}
public static void createAndShowCanvasGUI(){
    JFrame frm = new JFrame("State Pattern");
    frm.setVisible(true);
    frm.setSize(400, 400);
    frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frm.setContentPane(new SP());
}
public void paintComponent(Graphics g){
    super.paintComponent(g);

    g.setColor(state.getColor());
    g.fillRect(0, 0, getWidth(), getHeight());
    repaint();
}
public void init(){
    JButton push = new JButton("Push");
    JButton pull = new JButton("Pull");

    push.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent ae){
            if(ae.getActionCommand().equals("Push")){
                state.handlePush(this);
            }
        }
    });
    pull.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent ae){
            if(ae.getActionCommand().equals("Pull")){
                state.handlePull(this);
            }
        }
    });

    add(push);
    add(pull);
}
public State setState(State newState){
    State oldState = state; 
    state = newState;
    return oldState;
}
public State getState(){
    return state; 
    }
}

这是逻辑状态设计

public abstract class State {

public abstract void handlePull(SP p);
public abstract void handlePush(SP p);
public abstract Color getColor(); 
}

以下是州的一种变体

public class GreenState extends State{
@Override
public void handlePull(SP c) {
    c.setState(new BlackState());
}
@Override
public void handlePush(SP c) {
    // TODO Auto-generated method stub
    c.setState(new RedState());
}
@Override
public Color getColor() {
    return Color.GREEN;
    }
}

1 个答案:

答案 0 :(得分:5)

您对this的使用不是指SP个对象,而是指ActionListener个对象。

push.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent ae){
        if(ae.getActionCommand().equals("Push")){
            state.handlePush(this);  // *this* refers to anonymous inner-class ActionListener 
        }
    }
});

相反,您需要限定this参考

push.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent ae){
        if(ae.getActionCommand().equals("Push")){
            state.handlePush(SP.this);  // *this* now refers to SP
        }
    }
});

此处的更改为SP.this,而不是this

或者,您也可以将this分配给匿名类之外的最终变量,然后从内部引用该变量

final SP thisSp = this;
push.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent ae){
        if(ae.getActionCommand().equals("Push")){
            state.handlePush(thisSp);  // same as using SP.this
        }
    }
});