No se puede asignar la variable local final


Tengo una matriz de asientos, y la matriz tiene dos cadenas(seleccionadas y vacías). Al hacer clic en el ratón, quiero recorrer la matriz y encontrar el asiento seleccionado. Cuando presiono el botón dice:

La variable local final seatno no se puede asignar, ya que está definida en un tipo envolvente.

    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);
Author: ROMANIA_engineer, 2012-04-16

6 answers

El punto es que las variables método-locales del tipo que encierra son en realidad copiadas a instancias de clases anónimas (esto es debido a problemas de marco de activación, pero no voy a entrar en detalles ya que esto no es realmente relevante para la pregunta), por lo que deben ser finales, porque la variable en la instancia de tipo anidado ya no es la misma.

Así que, aquí está el primer ejemplo:

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

Esto no compila, porque no se puede hacer referencia a un variable no final en un método de clase anónima. Cuando agrega un modificador final a la declaración de a, el valor de a se copiará en la instancia creada de la clase anónima que ha definido. Sin embargo, no se le permitirá cambiar el valor de a, porque los cambios no serían visibles para el método donde se declaró a.

Sin embargo, las clases anónimas no son estáticas, es decir, tienen una referencia a la instancia que encierra (a menos que el método donde se declaran es estática) que puede utilizar para modificar las variables de la instancia que encierra:

int a = 3;

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

Este ejemplo compila y aumentaría a en 3 cada vez que se llame al método run() de la instancia de la clase anónima. (En este ejemplo nunca se llama, pero es solo un ejemplo.)

Por lo tanto, para resumir, debe convertir la variable seatno de una variable local de método a una variable de instancia del tipo envolvente. O, si es todavía, es necesario eliminar el final el modificador como variables finales solo se puede asignar una vez.

Actualización: En Java 8, se introduce el concepto de efectivamente final variables (ver Java Language Specification). Sin embargo, en el primer ejemplo de este post, la variable a se asigna varias veces, lo que evita que sea efectivamente final. Esto significa que este ejemplo todavía no compila con Java 8. (El error de compilación es " Variable local a definida en un ámbito que encierra debe ser final o efectivamente final")

 91
Author: Michael Schmeißer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-09 20:23:46

En lugar de definir una variable miembro de clase, también puede usar una int mutable para lograr lo mismo.

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

Dado que MutableInt no es un tipo primitivo (por lo tanto pasado por referencia) y puede ser reasignado, esto funciona.

 4
Author: Satyam Shekhar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-11 20:41:16

Una variable final no puede cambiar su valor (es similar a const de C/C++).

Probablemente quieras convertirlo en un campo de una clase (sin la palabra clave final, por supuesto), no en una variable local dentro de una función.

 3
Author: gulyan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-15 22:03:02

Recientemente me enfrenté a un problema similar. En mi caso, era más fácil crear una matriz final (o colección) y agregar variable, que quería cambiar dentro de la clase anónima, a esta matriz, como se muestra a continuación.

   int a = 3;
   final int[] array = new int[1];
   array[0] = a;
   new Runnable() {
       @Override
       public void run() {
           array[0] += 3;
       }
   };
 1
Author: yurin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-26 17:00:35

Sin conocer la declaración de seatno, sugeriría introducir una nueva variable en el método mouseClicked() que es no final y hace el mismo trabajo que seatno actualmente, ya que la variable parece solo ser utilizada dentro de ese método.

Por cierto: Escribe en mayúscula los nombres de tus clases (data debe ser Data). Se verá mucho más claro.

 0
Author: Yogu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-15 22:02:58

Asegúrese de que su variable no tenga el modificador 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;

También, para comparar Cadenas debes usar equals:

if(anArray[x].equals("selected"))
 0
Author: Luiggi Mendoza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-15 22:04:25