2012-04-15 33 views
33

Tengo una matriz de asientos, y la matriz tiene dos cadenas (seleccionada y vacía). Al hacer clic con el mouse, quiero atravesar la matriz y encontrar el asiento seleccionado. Cuando presiono el botón, dice:No se puede asignar la variable local final

No se puede asignar la variable local final seatno, ya que está definida en un tipo adjunto.

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

su variable 'seatno' tiene la palabra clave final en el mismo. –

Respuesta

89

El punto es que las variables del método local del tipo envolvente son en realidad copian a instancias de clases anónimas (esto se debe a de los problemas del marco de activación, pero no profundizaré en los detalles ya que esto no es realmente relevante para la pregunta), por lo que deben ser definitivos, porque la variable en la instancia de tipo anidado ya no es la misma.

lo tanto, aquí es 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 una 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áticos, es decir, tienen una referencia a la instancia que encierra (a menos que el método en el que se declaran es estática) que se puede utilizar para modificar las variables de la instancia adjuntando:

int a = 3; 

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

Este ejemplo se compila y aumentaría a por 3 cada vez que se llama 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 de método local a una variable de instancia del tipo adjunto.O, si aún es así, debe eliminar el modificador final ya que las variables finales solo se pueden asignar una vez.

Actualización: En Java 8, se introduce el concepto de variables de eficacia finales (ver Java Language Specification). Sin embargo, en el primer ejemplo de esta publicación, la variable a se asigna varias veces, lo que impide que sea efectivamente definitiva. Esto significa que este ejemplo aún no compila con Java 8. (El error de compilación es "La variable local definida en un ámbito envolvente debe ser definitiva o efectivamente definitiva")

0

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

Por cierto: escriba con mayúscula sus nombres de clase (data debe ser Data). Se verá mucho más claro.

3

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

Probablemente desee convertirlo en un campo de una clase (sin la palabra clave final del curso), no como una variable local dentro de una función.

0

Asegúrate de que tu 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; 

Además, para comparar cadenas se debe utilizar equals:

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

En lugar de definir una variable de 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); 
     } 
    }; 
} 

Desde MutableInt no es tipo primitivo (de ahí pasado por referencia) y pueden ser reasignados esto funciona.

+3

Nota: MutableInt requiere Apache Commons Lang. – Sundae

+0

Bien, gracias. MutableInt es más conveniente que AtomicInteger, porque hay menos códigos (se necesita menos código) – Hartmut

1

Hace poco tuve un problema similar. En mi caso, fue más fácil crear la matriz final (o colección) y agregar la 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; 
     } 
    }; 
Cuestiones relacionadas