怎么可能我的类字段改变了,虽然它定义的静态?

时间:2012-01-17 12:46:55

标签: class static constructor field

不幸的是,我有一个错误,我现在已经工作了整整一天,虽然我知道有办法解决它,但我很高兴知道我的逻辑出错了。

现在,我的节目是关于两队棋手之间的比赛。它根据教练(用户)选择的球员设置预测得分。 *(我的问题下面有更多背景信息)

所以我首先询问用户哪些玩家在他的团队中。当然,我希望这个“PlayerList”信息保持不变(我提到的错误就是它神秘地没有)

所以我制作了一个弹出所有棋盘的Gui,玩家按照用户提交给程序的顺序。然后每当他点击其中一个按钮时,该按钮的acionlistener就会显示下一个玩家(并且它让主程序知道在该板上选择了另一个玩家并相应地调整预测,但这些任务完美地工作)。

现在,问题在于,如果用户已经为第2板上的其他人替换了Marcel,那么当用户要点击第3板的按钮时,他就不再拥有Marcel的选项了。所有按钮的“playerList”字段已设置为主程序中所选的播放器设置,而不是主程序在运行开始时提示用户的原始列表...

(见附图)enter image description here

因此,分配给这些按钮的玩家与用户实际选择的玩家列表之间存在一些非常恼人的依赖关系。如果我查看我的代码,我无法理解为什么......

所以我定义的按钮出了问题。

现在这就是我们所拥有的:

我扩展了JButton,因此该按钮具有用户团队中可用玩家的信息,如下所示:

    public class JButtonPlus extends JButton {
public Team team;
private int aantalSpelers;
final ArrayList<Player> playerList;
private Integer spelerNr;
private Integer bordNr;


public JButtonPlus(ArrayList<Player>playerList_, Integer spelernr, Integer bordnr){

    playerList=playerList_;
    aantalSpelers=playerList_.size();
    spelerNr=spelernr;
    bordNr = bordnr;
}

所以问题是这个最终的ArrayList playerList根本不是常量。

通过单击任何其他按钮调用任何actionListener后,它会发生变化。

这是主程序中的代码,用于创建按钮并添加actionlisteners: (注意:这个teams.get(0)指的是用户的团队,而现场玩家指的是一个ArrayList,里面装满了他提交给程序的所有玩家。方法displaySpelernr(i)将玩家名称添加到JButtonPlus的setText方法)

Box verticalBox_1 = Box.createVerticalBox();
    frame.getContentPane().add(verticalBox_1);

    JLabel lblNewLabel = new JLabel("opstelling thuisteam");
    verticalBox_1.add(lblNewLabel);

    for (int i = 0; i < teams.get(0).players.size(); i++) {
        final JButtonPlus btnSpeler = new JButtonPlus(
                teams.get(0).players,i, i);

        btnSpeler.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent arg0) {
                btnSpeler.displayVolgendeSpeler();

            }
        });
        verticalBox_1.add(btnSpeler);
        btnSpeler.displaySpelerNr(i);
    }

在userClick上调用的方法,displayVolgendeSpeler就是这样的

    public void displayVolgendeSpeler(){
spelerNr =(spelerNr+1)%aantalSpelers;
    displaySpelerNr(spelerNr);      

问题在于声明,其他声明涉及计算,其工作方式应该如此。这个displaySpelerNr()方法看起来像他的

public void displaySpelerNr(Integer i){ setText(playerList.get(i).SpelerNaam); 并且在这里注意到bug:playerList对象已被更改..

当有人点击按钮时,是否有人知道为什么这个假想的玩家玩家列表的常量来源会发生变化?

*(更多背景信息) 两个国际象棋之间的比赛涉及所有球员与一个对手球员进行一场比赛。通常情况下,团队中的球员具有不同的力量。因此,举例来说,如果你的球队A的球员实力从初学者到高手,而球队B的球员范围从中级到大师,你知道如果你根据增加的力量配对球员,那么球队A肯定会失败。当A队通过将他们与B队的两个最强的球员配对而牺牲一两个最弱的球员时,这种乐趣就开始了。这意味着失去了两分,但是A队的其余球员现在每个人都会面对一个较弱的球员而不是一个更强大的。甚至可能存在配对,因此较弱的团队更有可能获胜。我的程序试图显示哪些配对最差且最好,并提供统计数据。当然,如果可能使用这个程序的教练实际上能够将这个Gui设置在他想要的团队中,这将是很好的,这就是你进来的地方,亲爱的StackOverflow-冠军!

1 个答案:

答案 0 :(得分:1)

将字段声明为final表示您无法为其指定新值。但是,如果该字段包含Object,您仍然可以修改该Object内部的非final字段。下面的代码应说明我的意思。

class Foo {
    private final Bar foo; 

    public Foo() {
        foo = new Bar();
    }

    public void testFoo() {
        this.foo = new Bar(); // compile error
        this.foo.setBar("Test"); // works fine
    }
}

class Bar {
    private String bar;

    public void setBar(String bar) {
        this.bar = bar;
    }

    public String getBar() {
        return bar;
    }
}

在您的代码中,您有final ArrayList<Player>,这意味着您无法在该字段中存储 ArrayList。但是,您可以通过任何常用方式(添加,删除,更新元素等)修改现有ArrayList的内容。

您还将相同的ArrayList传递给所有JButtonPlus实例,因此在任何这些类中更改它都会导致对所有这些实例进行更改。尝试传入ArrayList的副本,看看是否能解决问题。