¿Por qué dice que "No se puede hacer referencia a una variable no final i dentro de una clase interna definida en un método diferente"?

Tengo botón de escuchar y en el método onCreate() tengo una variable local como

  onCreate() { super.onCreate(); int i = 10; Button button = (Button)findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { i++; } }); 

¿Por qué java pide que me haga final?

Cuando el método onCreate () devuelve, su variable local se limpia de la pila, por lo que ya no existirán. Pero el objeto de clase anónimo nuevo View.OnClickListener () hace referencia a estas variables. De causa es el comportamiento incorrecto por lo que java no le permiten hacer esto.

Después de que es final se convierte en una constante. Así que se almacena en el montón y se puede utilizar con seguridad en las clases anónimas.

Su clase interna anónima se refiere a su ámbito de inclusión al tomar copias de las variables locales – si desea cambiar el valor de un int en una clase interna anónima, debe hacer un poco de hackery:

 final int[] arr = new int[1]; arr[0] = 10; Button button = (Button)findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { arr[0]++; } 

Porque estás accediendo a ella dentro de una clase interna anónima. No puedes hacer eso. Puedes hacerlo final y luego leerlo de la clase interna anónima, pero luego no puedes incrementarla.

Opciones:

  • Hacer una variable de instancia de la clase externa en su lugar
  • Convertirlo en una variable de instancia de la clase interna anónima
  • Utilice un contenedor – por ejemplo, una matriz de un solo elemento, un AtomicInteger o algo así

Probablemente me favorecería la segunda opción a menos que necesitara conseguir en i de cualquier otro lugar. Considero la tercera opción como un poco desagradable hack, para ser honesto.

Hacer que la variable final sea ​​necesaria porque bajo la campana, las clases internas anónimas como esa son simplemente azúcar sintáctico que se compila a una clase anidada fuera del alcance del método que contiene.

Esto significa que ninguna de las variables declaradas dentro del método es accesible a la clase interna, por lo que el compilador extrae otro truco – y copia el valor en un constructor oculto para su clase. Para evitar la confusión del programador donde esta copia no se actualiza para coincidir con los cambios en la variable en el método, debe ser definitiva para asegurarse de que no hay tales cambios.

Puesto que su objetivo aquí es tener un número entero de incremento, y sólo la referencia debe ser final (el objeto en sí no necesita ser inmutable) podría declarar un final AtomicInteger i y luego incrementarlo como desee desde la devolución de llamada.

Puesto que necesitas incrementar la variable i no puedes hacerlo definitivo. Podrías convertirlo en un miembro de la clase.

  • Cómo comparar una cadena de Intent.getStringExtra ()?
  • Java.lang.OutOfMemoryError en almacenar imágenes en sqlite db
  • Android: SMSManager - Intento de obtener longitud de matriz nula
  • Cómo utilizar Smack 4.1 en Android?
  • ¿Estancado en la pantalla del emulador en Eclipse con Android Development?
  • En Java, ¿cómo verifica si una variable float es null?
  • ¿Debo evitar estrictamente el uso de enums en Android?
  • Https conexión Android
  • ¿Una clase anónima mantiene referencias externas vivas?
  • ¿Puedo obtener una notificación cada vez que el usuario interactúa con un dispositivo Android?
  • ¿Es posible ejecutar una cadena de código Java en tiempo de ejecución en Android?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.