2013-04-24 5 views
-3

Хорошо, это, наверное, что-то простое, но я просто не могу его получить.Статические поля Java, не работающие с наследованием

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

Все это хорошо, оно возвращает true для println. Теперь это фактическая проблема ... У меня есть оператор if if if(Vars.foo) Это -хорошо работать, правильно? Он никогда не выполняет код внутри скобок if, ЕСЛИ я не добавляю эту строку кода над ним.

System.out.println(Vars.foo); 

Это, естественно, печатает так, то если работает оператор, но если я закомментировать эту строку, она не работает.

Я также прибегая к помощи, и попытался это:

Vars v = null; 
if(v.yoo) 

Это еще не будет делать это, если я не имею Println, я понятие не имею, почему Println делает его работу. Можете ли вы объяснить, почему и как это работает?

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

    } 
} 

}

Это та часть, которая не работает, если заявление. всегда возвращает false.

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

фрейм часть называется в новой системе отсчета, то другой класс называется там, с классом Vars называется в обеих. в painthandling() оператор if возвращает false, если у него нет println.

+0

Можете ли вы опубликовать код, который, как вы говорите, не работает? –

+3

Где часть наследства вашего вопроса? – NilsH

+0

Как это сейчас? –

ответ

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 делает его печать. Но, что интересно, это может быть любое утверждение 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() внутри цикла в то время, когда делаются тест. Причина, по которой это работает, когда System.out.println, вероятно, потому, что синхронизирован println. И фактически, любая синхронизированная операция внутри цикла имеет тот же эффект. Таким образом, это проблема с потоками (модель памяти), и ее можно решить, отметив переменную как volatile. Но это не меняет того факта, что выполнение многопоточного доступа со статической переменной - плохая идея.

Предлагаю прочитать Chapter 17 of the Java Language Specification, чтобы узнать больше о потоках, синхронизации и модели памяти Java.

-1

Я действительно не читал ваше сообщение, но после того, как он скроется, похоже, вы пытаетесь использовать статический метод, подобный этому.

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

Хорошая вещь о статическом методе и поля является то, что вы не должны их экземпляры, попробуйте вместо этого:

someMethod() { 
    boolean bool = Var.foo 
} 
+0

Это правда, но это не связано с реальной проблемой. – NilsH

+0

Ouch для понижающего голоса, но в любом случае я предполагаю, что вызов sys out запускает компилятор для оптимизации кода и исправления ошибки в цикле if. – Dan

+0

Извините. Не значит быть отрицательным. Просто укажите, что проблема - это что-то другое. Способ обращения к переменной (по экземпляру или по классу) не должен иметь никакого значения. Возможно, вы правильно знаете sys, но настоящая проблема, вероятно, связана с потоками. – NilsH

Смежные вопросы