-3

Alright, this is probably something simple, but I just can't get it.

    package foo.foo.foo;

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

Alright, so that's my Vars class.

I then have a JFrame, with a JMenuBar,JMenu,and a 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);

All is good, it returns true for the println. Now, this is the actual problem part... I have a if statement if(Vars.foo) This -should- work, right? It never executes the code inside the if brackets, UNLESS I add this line of code above it.

System.out.println(Vars.foo);

That naturally prints true, then the if statement works, but if I comment out that line, it doesn't work.

I've also been googling, and tried this:

Vars v = null;
if(v.yoo)

That still won't do it unless I have the println, I have no idea why the println makes it work. Can you explain why/how this works?

Edit:

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

    }
}

}

That's the part that's not working, the if statement. always returns false.

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

The JFrame part is called in the new frame, then the other class is called there, with the Vars class called in both. in painthandling(), the if statement returns false if it doesn't have the println.

Chris Shafer
  • 68
  • 1
  • 6
  • can you post the code that you say doesn't work? – Pradeep Pati Apr 24 '13 at 20:14
  • 3
    Where's the inheritance part of your question? – NilsH Apr 24 '13 at 20:15
  • I still see no inheritance... Anyway, why is the field static in the first place? Seems like a _very_ bad idea to have a static field accessed by (possibly) multiple threads. – NilsH Apr 24 '13 at 20:21
  • How do you know the code isn't being executed? More likely it IS running and you don't realise it – Bohemian Apr 24 '13 at 20:24
  • If I don't have it as static, it errors out like, everywhere. I've tried making it non-static, and doing Vars v = null; v.foo, but I got the same result As for the running, I have printlns in there that aren't getting fired off. – Chris Shafer Apr 24 '13 at 20:24
  • What kind of errors? This seems like a more fundamental problem than just having problems with a static variable (that you're getting "errors everywhere" when making it an instance variable is a good indication...). Doing a System.out.println of the variable, or assigning an instance to null, shouldn't make any difference. As mentioned, multiple threads accessing/setting the same static variable could cause a multitude of problems. – NilsH Apr 24 '13 at 20:29
  • possible duplicate of [Loop doesn't see changed value without a print statement](http://stackoverflow.com/questions/25425130/loop-doesnt-see-changed-value-without-a-print-statement) – Boann Aug 25 '14 at 15:51
  • Hey mate, I wrote this question over a year ago. – Chris Shafer Aug 26 '14 at 01:33

2 Answers2

1

Short answer: Make the variable volatile

Long answer:

I have done some testing, and I can actually reproduce your situation (at least I think it's the same). Consider this code:

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

            }

        }

    }
}

This never prints I'm here. However, as the OP states, adding a System.out.println to the while loop does make it print it. But interestingly enough, it can be any println statement. It doesn't need to print the variable value. So this works:

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

        }

    }
}

There are some other cases that also produces the "expected" output, and that is making the variable volatile, or doing a Thread.sleep() inside the while loop where the test is done. The reason it works when the System.out.println is probably because println is synchronized. And in fact, doing any synchronized operation inside the loop have the same effect. So to conclude, it's a threading (memory model) issue, and it can be resolved by marking the variable as volatile. But this does not change the fact that doing multithreaded access with a static variable is a bad idea.

I suggest reading Chapter 17 of the Java Language Specification to learn more about threads, synchronization and the Java memory model.

NilsH
  • 13,705
  • 4
  • 41
  • 59
-1

I didn't really read your post but after skimming it looks like you are trying to use the static method like this.

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

The nice thing about static method and fields is that you don't have to instantiate them, try this instead:

someMethod() {
    boolean bool = Var.foo
}
Dan
  • 1,179
  • 2
  • 10
  • 18
  • This is true, but it is not related to the actual problem. – NilsH Apr 24 '13 at 20:31
  • Ouch for the down vote, but anyway I'm guessing the sys out call triggers the compiler to optimize the code and fix the bug in the if loop as well. – Dan Apr 24 '13 at 20:36
  • Sorry about that. Didn't mean to be negative. Just point out that the problem is something else. The way he accesse the variable (by instance or by class) shouldn't make any difference. You might be correct about the sys out, but the real problem is probably threading related. – NilsH Apr 24 '13 at 20:41
  • I had everything on one thread before, and it still caused the same problem, I don't think it's a thread issue. – Chris Shafer Apr 24 '13 at 20:44