-3

好吧,这可能很简单,但我就是不明白。

    package foo.foo.foo;

public class Vars {
    public static boolean foo = false;
}

好的,这就是我的 Vars 课程。

然后我有一个 JFrame,有一个 JMenuBar、JMenu 和一个 JMenuItems。

  items = new JCheckBoxMenuItem("Foo");
        items.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                AbstractButton ab = (AbstractButton)e.getSource();
                Vars.foo = ab.getModel().isSelected();
                System.out.println(Vars.foo);
            }
        });
    menu.add(items, 0);
    menuBar.add(menu,0);

一切都很好,它为 println 返回 true。现在,这是实际的问题部分......我有一个 if 语句 if(Vars.foo) 这 - 应该 - 工作,对吗?它从不执行 if 括号内的代码,除非我在它上面添加这行代码。

System.out.println(Vars.foo);

这自然打印为 true,然后 if 语句有效,但如果我注释掉该行,它就不起作用。

我也一直在谷歌搜索,并尝试了这个:

Vars v = null;
if(v.yoo)

除非我有 println,否则仍然不会这样做,我不知道为什么 println 使它工作。你能解释一下为什么/如何工作吗?

编辑:

public class painthandling implements Runnable {
@Override
public void run() {
    Vars y = null;
    while(true){
        if(y.foo){
            //some code here
        }
        System.out.println(y.foo);

    }
}

}

那是不工作的部分,if 语句。总是返回假。

       frame f = new frame();
       (new Thread(new painthandling())).start();
        System.out.print("Got it.");

JFrame 部分在新框架中被调用,然后另一个类在那里被调用,Vars 类在两者中被调用。在painthandling() 中,如果if 语句没有println,则返回false。

4

2 回答 2

1

简短回答:制作变量volatile

长答案:

我做了一些测试,我实际上可以重现你的情况(至少我认为它是一样的)。考虑这段代码:

public class Test {
    public static boolean foo = false;

    public static void main(String[] args) {

        new Thread(new Runnable(){

            @Override
            public void run() {
                while(true) {
                    try {
                        Thread.sleep(2000);
                        System.out.println("Swapping");
                        Test.foo = !Test.foo;
                    }
                    catch(Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

        while(true) {
            if(Test.foo) {
                System.out.println("I'm here");

            }

        }

    }
}

这从不打印I'm here。但是,正如 OP 所述System.out.println,在 while 循环中添加 a 确实会使其打印出来。但有趣的是,它可以是任何 println 语句。它不需要打印变量值。所以这有效:

public class Test {
    public static boolean foo = false;

    public static void main(String[] args) {

        new Thread(new Runnable(){

            @Override
            public void run() {
                while(true) {
                    try {
                        Thread.sleep(2000);
                        System.out.println("Swapping");
                        Test.foo = !Test.foo;
                    }
                    catch(Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

        while(true) {
            if(Test.foo) {
                System.out.println("I'm here");

            }
            System.out.println(""); // Doesn't have to be System.out.println(Test.foo);
            // This also works (lock is just an object)
            // synchronized(lock) {
            //     int a = 2;
            // }

        }

    }
}

还有一些其他情况也会产生“预期的”输出,那就是制作变量volatile,或者在Thread.sleep()完成测试的 while 循环内进行。它工作的原因System.out.println可能是因为println是同步的。事实上,在循环内进行任何同步操作都具有相同的效果。总而言之,这是一个线程(内存模型)问题,可以通过将变量标记为volatile. 但这并没有改变使用静态变量进行多线程访问是一个坏主意的事实。

我建议阅读Java 语言规范的第 17 章,以了解有关线程、同步和 Java 内存模型的更多信息。

于 2013-04-24T21:17:54.560 回答
-1

我并没有真正阅读您的帖子,但在浏览后看起来您正在尝试使用这样的静态方法。

someMethod() {
    Var var = null;
    boolean bool = var.foo
}

静态方法和字段的好处是你不必实例化它们,试试这个:

someMethod() {
    boolean bool = Var.foo
}
于 2013-04-24T20:25:58.647 回答