¿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 usar el cliente Apache HTTP heredado en Android Marshmallow?
  • Capa de acceso a datos para Android
  • Error: Ejecutando el comando 'ant', asegúrate de haber instalado y añadido hormigas a tu ruta de acceso
  • ¿Podría pasar Context a un método auxiliar estático como un argumento potencialmente causar una pérdida de memoria?
  • Org.w3c.dom.Document a String sin javax.xml.transform
  • ¿Qué es List <?> En Java (Android)?
  • Android redibujar diseño de forma programática
  • Java: Eficaz ArrayList filtrado?
  • Almacenamiento de clave secreta en KeyStore sin el parámetro ProtectionParameter
  • ¿Cómo aceptar la solicitud de amigos correctamente en Android smack?
  • Convertir o transmitir un objeto simple a objeto de otra clase
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.