2014-01-25 5 views
1

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

Итак, вот что: у меня есть метод, который я вызываю, и у меня есть кнопка, которая изменит значение x. В зависимости от значения x, я хочу, чтобы программа что-то делала. Ниже программа не очень полная, но вы получите идею:

public class foo{ 
     private void do(){ 
     int x=0; 
     JButton changeValue= new JButton("Change the value of x"); 
     changeValue.addActionListener(new ActionListener(){ 
     @Override 
     public void actionPerformed(ActionEvent e){ 
         x=10; //change the x value when the button is clicked 
          //Here the user may also change the value of x 
          //by inputting some other number 
       } 
      }); 
     //Something happens depending on x 
     //But nothing happens here because when I get the value of x, 
     //it reverts back to 0. 
     } 
} 

Однако, независимо от того, где я заявляю о своем х в делах(), я получаю сообщение об ошибке, говорящей мне, что внутренний класс не может получить доступ к переменному внешнему классу и что они должны быть объявлены окончательными. Но я не могу объявить его окончательным, потому что мне нужно изменить его позже. Я попытался поместить значения в новый класс. Я также попробовал объявить x как член foo(), но это приводит к тому, что x равен 0 или null, потому что по какой-то причине, когда он выходит из метода нажатия кнопки, для возврата к своему старому значению требуется значение x: 0 или null.

Что мне нужно: при нажатии кнопки изменяется значение x (Предполагая, что пользователь может изменить значение x на какой-то другой номер). Спасибо за любые ответы заранее.

+0

Тот факт, что это ваш первый вопрос, не оправдывает вас тем, что вы не искали этот вопрос перед тем спрашивайте. – mjkaufer

+0

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

ответ

2

Вам необходимо создать ссылку final на вашу переменную x.

Поскольку это примитивный тип, создать класс, чтобы обернуть его:

private static class MyX { 
    int x; 
    // + getter and setter 
} 

А потом:

final MyX myX = new MyX(x); 
JButton changeValue= new JButton("Change the value of x"); 
changeValue.addActionListener(new ActionListener(){ 
    @Override 
    public void actionPerformed(ActionEvent e){ 
     myX.setX(10); 
    }); 
// get the value of MyX back if necessary 
+0

Да, спасибо, что это сработало ... :) Итак, я все еще могу манипулировать данными, создавая окончательную ссылку - но почему это должно быть в объекте? Это только один способ сделать это? – Hans

0

Проблема заключается в том: когда вы создаете что ActionListener вы объявляя, что будет actionPerformed выполняться через некоторое время. Вы не можете изменить x из actionPerformed, потому что x существует только внутри этого вызова метода.

class Foo { 
    void doSomething() { 

     int x = 0; // x inside doSomething 

     JButton btn = new Button("Do Something"); 

     btn.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent ae) { 
       /* 
       * This does not happen now: 
       * it happens later. 
       * 
       * By the time this happens 
       * the method will have exited 
       * and x will be gone. 
       * 
       */ 
      } 
     }); 

     /* That x disappears forever here. 
     * (Or a little bit later but basically here.) 
     */ 
    } 
} 

Вы можете объявить й как окончательные, а затем анонимный класс присваивается значение его, но вы хотели изменить его. Возможно, что вы хотели, чтобы сделать это поле:

class Foo { 

    int x = 0; // x inside Foo 

    JButton btn = new Button("Do Something"); 

    Foo() { 
     btn.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent ae) { 
       /* do something with x as needed */ 
      } 
     }); 
    } 
} 

Анонимные классы также могут иметь поля:

btn.addActionListener(new ActionListener() { 
    int x = 0; // x inside anonymous ActionListener 

    @Override 
    public void actionPerformed(ActionEvent ae) { 
     /* use x only in actionPerformed */ 
    } 
}); 

«Я также пытался объявить х как член Foo(), но что результаты x равны 0 или null, потому что по какой-то причине, когда он выходит из метода нажатия кнопки, для возврата к своему старому значению требуется x: 0 или null. "

К сожалению, это, вероятно, означает, что вы делаете что-то еще неправильно. Я не уверен, что это может быть из вашего описания и кода. Например, вы создаете новый JButton локально внутри метода, который кажется необычным. Если это не один из методов «createAndShowGUI» (как видно по всему Swing tutorials), возможно, вы создаете несколько кнопок, несколько прослушивателей и т. Д.

+0

Я никогда не использовал поля раньше ... это будет следующая вещь в моем списке, спасибо :) и да, я знаю, что мой код немного необычен, но я все еще участвую. Если бы я должен был создать графический интерфейс, где мне не приходилось создавать несколько кнопок и слушателей, как бы я это сделал? – Hans

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