Подтвердить что ты не робот

Конечная локальная переменная не может быть назначена

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

Конечная локальная переменная 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);
4b9b3361

Ответ 1

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

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

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

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

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

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

Ответ 2

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

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

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

Ответ 3

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

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

Ответ 4

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

   int a = 3;
   final int[] array = new int[1];
   array[0] = a;
   new Runnable() {
       @Override
       public void run() {
           array[0] += 3;
       }
   };

Ответ 5

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

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

Ответ 6

Убедитесь, что ваша переменная не имеет модификатора 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"))