2012-04-15 12 views
33

У меня есть массив сидений, и массив имеет две строки (выбранные и пустые). При щелчке мыши я хочу пересечь массив и найти выбранное место. Когда я нажимаю кнопку, он говорит:Конечная локальная переменная не может быть назначена

Конечная локальная переменная seatno не может быть назначена, так как она определена в закрытом типе.

JButton btnContinue = new JButton("Next"); 
    btnContinue.addMouseListener(new MouseAdapter() { 
     public void mouseClicked(MouseEvent arg0) { 

      for(int x=0;x<17;x++){ 
       if(anArray[x]=="selected"){ 

        seatno = anArray[x]; 
       } 
      } 

      data page=new data(newfrom,newto,newtime,date2,seatno); 
      page.setVisible(true); 
      setVisible(false); 
     } 
    }); 
    btnContinue.setBounds(358, 227, 62, 23); 
    contentPane.add(btnContinue); 
+0

Ваша переменная 'seatno' имеет в ней последнее ключевое слово. –

ответ

89

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

Итак, вот первый пример:

void foo() { 
    int a = 3; 
    new Runnable() { 
     @Override 
     public void run() { 
      a += 3; 
     } 
    }; 
} 

Это не компилируется, потому что вы не можете ссылаться на неконечное переменную в методе анонимного класса. Когда вы добавляете окончательный модификатор к объявлению a, значение a будет скопировано в созданный экземпляр анонимного класса, который вы определили. Однако вам не будет позволено изменять значение a, поскольку изменения не будут видны методу, в котором объявлен a.

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

int a = 3; 

void foo() { 
    new Runnable() { 
     @Override 
     public void run() { 
      a += 3; 
     } 
    }; 
} 

Этот пример компилируется, и он будет увеличивать a на 3 каждый раз, когда вызывается метод вызова экземпляра анонимного класса. (В этом примере это никогда не вызывается, но это просто пример.)

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

Обновление: В Java 8, понятие эффективно конечных переменных вводится (см Java Language Specification). Однако в первом примере этого сообщения переменная a назначается несколько раз, что предотвращает ее окончательную окончательность. Это означает, что этот пример до сих пор не компилируется с Java 8. (Ошибка компиляции: «Локальная переменная a, определенная в охватывающей области, должна быть окончательной или эффективной окончательной»)

0

Не зная декларацию seatno, я предлагаю ввести новую переменную в mouseClicked() метод, который не окончательным и делает ту же работу, как seatno в настоящее время делает, так как переменная только кажется для использования внутри этого метода.

К слову: капитализировать имена своих классов (data должно быть Data). Будет выглядеть намного яснее.

3

Конечная переменная не может изменить ее значение (она похожа на const из C/C++).

Возможно, вы захотите сделать это полем в классе (без конечного ключевого слова, конечно), а не локальной переменной внутри функции.

0

Убедитесь, что ваша переменная не имеет модификатора final.

//final, can be set only when the object is created. 
private final String seatno; 

//no final modifier, the value can be set every time you "want" 
private String seatno; 

Кроме того, для сравнения строк, вы должны использовать equals:

if(anArray[x].equals("selected")) 
4

Вместо определения переменной-члена класса вы также можете использовать измененный int для достижения того же.

void foo() { 
    final MutableInt a = new MutableInt(3); 
    new Runnable() { 
     @Override 
     public void run() { 
      a.add(3); 
     } 
    }; 
} 

Поскольку MutableInt не является примитивным типом (следовательно, передан по ссылке) и может быть переназначен, это работает.

+3

Примечание: MutableInt требует Apache Commons Lang. – Sundae

+0

Ницца, спасибо. MutableInt более удобен, чем AtomicInteger, потому что меньше codemell (требуется меньше кода) – Hartmut

1

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

int a = 3; 
    final int[] array = new int[1]; 
    array[0] = a; 
    new Runnable() { 
     @Override 
     public void run() { 
      array[0] += 3; 
     } 
    }; 
Смежные вопросы