¿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?
- Cómo manejar la falla de AsyncTask
- Gradle Método DSL no encontrado: storeFile ()
- Timer.scheduleAtFixedRate no se detiene cuando llamo cancelar
- Eliminando un elemento de String array en android
- Double buffering en Java en Android con lienzo y vista de superficie
- Android SDK r18 parece haber roto ORMLite
- Smack 4.1 No hay respuesta dentro del tiempo de espera de respuesta
- Obtener un nombre corto de tres letras de tiempo (en contraposición a cuatro letras)?
- Debe llamar a removeView () en el padre del niño primero con AlertView
- Cómo evitar que aparezca automáticamente el teclado de Android cuando comience la actividad
- Android, el arranque de matriz de Java no está permitido aquí
- Android: Personajes dejados atrás en EditText
- ¿Cómo descargar múltiples archivos simultáneamente usando intentservice en Android?
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.
- Comparación de dos cuerdas no funciona en android
- TabWidget onClick after onSaveInstanceState (java.lang.IllegalStateException: No se puede realizar esta acción después de onSaveInstanceState)