2010-12-29 23 views
11

En el siguiente código si elimino la palabra clave final de EditText, estoy obteniendo un error en la línea (6) donde paso el objeto EditText (et) a la intención ... Tengo que conocer el significado de la palabra clave final aquí. ..¿Cuál es el uso de la palabra clave final?

final EditText et=(EditText)findViewById(R.id.t); 
     Button b=(Button)findViewById(R.id.b1); 
     b.setOnClickListener(new Button.OnClickListener(){ 
      public void onClick(View v)<br> 
      { 
      Intent on=new Intent(Intent.ACTION_CALL,Uri.parse("tel:"+et.getText())); 
      startActivity(on); 
      } 
     }); 
+0

androide: ¿Puede decirnos, qué error que había conseguido en su Logcat? –

+0

no es tiempo de ejecución era un error de tiempo de compilación. Era "No se puede hacer referencia a una variable no final y dentro de una clase interna definida en un método diferente" esto es lo que obtuve ... –

Respuesta

15

Es porque utilizas el cierre aquí. Significa que la clase interna usa el contexto del que está dentro de uno. Para usarlo, las variables deben declararse finales para no ser modificadas.

Ver más here.

+0

siento a qué se refiere. clase interna aquí ... ¿es OnClickListener? –

+0

por supuesto es una clase anonymouse que implementa OnClickListener. –

+0

ok lo tengo gracias ... –

2

Final hace que la variable et solo permita asignarse una vez. También cambia el alcance de la variable y permite la función onClick visibility a et. Sin la final, et no es visible dentro de la función onClick.

+0

cómo las marcas finales y visibles para onClick ¿pueden dar más detalles al respecto? –

20

Final significa esencialmente que la variable et no será reasignada en ningún punto y se mantendrá. Esto significa que las clases internas, como su oyente, pueden confiar en que no será reasignado por otro hilo que pueda causar todo tipo de problemas.

final también se puede utilizar para modificar un método o definición de clase, lo que significa que el método no puede ser reemplazado por una subclase, o que la clase no se puede extender.

+0

interesante Nunca supe que el final podría usarse en un método para tal efecto. Debería ser útil en algún momento en el futuro. – schwiz

+0

Diciendo "la variable' et' no será reasignada "es más correcto. 'final' se aplica a una variable, no al objeto al que se hace referencia. – barjak

0

Here is a link que analiza la palabra clave final. De acuerdo con the specification (sección 4.12.4):

Una variable puede ser declarada definitiva. Una variable final solo se puede asignar a una vez. Es un error de tiempo de compilación si se asigna una variable final a menos que definitivamente no esté asignada (§16) inmediatamente antes de la asignación.

3

Leer this article para entender los detalles de implementación involucrados:

La razón de esta restricción se hace evidente si tenemos que verter algo de luz sobre cómo las clases local de aplicación. Una clase local anónima puede usar variables locales porque el compilador le da automáticamente a la clase un campo de instancia privada para contener una copia de cada variable local que usa la clase. El compilador también agrega los parámetros ocultos a cada constructor para inicializar estos campos privados creados automáticamente. Por lo tanto, una clase local no tiene acceso a las variables locales , sino simplemente a sus propias copias privadas de . La única forma en que esto puede funcionar correctamente es si las variables locales se declaran definitivas, de modo que se garantiza que no cambien . Con esta garantía, la clase local está segura de que sus copias internas de las variables reflejan con exactitud las variables locales reales .

EDIT:

Berlín Brown dice: "He publicado una versión descompilación de una clase interna anónima .Pero para ser honesto, todavía no veo por qué el compilador tiene que tener esa información. Incluso si el campo se declara final, el campo aún puede ser nulo. Creo que esta es una de esas peculiaridades de Java, usted tiene que declarar ese campo final ... porque así es como es. No hay una razón clara por la"

La razón es asegurarse de que los usuarios se dan cuenta de que los cierres 'se cierran sobre' variables y no valores. Supongamos que no había ningún requisito de tener variables locales finales. A continuación, podríamos escribir código como:

public void doIt() { 
    for(int i = 0; i < 3; ++i) { 
     runnables.add(new Runnable() { 
      @Override 
      public void run() { 
       System.out.println(i); 
      } 
     }); 
    } 
    run(runnables); // run each runnable 
} 

¿Qué opinas sería la salida Si cree que sería "0 1 2" que sería un error ya que el Ejecutable se cierra sobre la "variable" i y no? "valor" de i en ese punto en el tiempo y, por lo tanto, la salida sería "2 2 2". ¿Qué se puede hacer para lograr el comportamiento esperado aquí? Dos soluciones: o confían en los usuarios para h Entender cómo funcionan los cierres o de alguna manera hacer que se aplique en el nivel del idioma. Y es la segunda opción con la que los diseñadores de idiomas se han ido.

public void doIt() { 
    for(int i = 0; i < 3; ++i) { 
     final int j = i; // notice the final local variable 
     runnables.add(new Runnable() { 
      @Override 
      public void run() { 
       System.out.println(j); 
      } 
     }); 
    } 
    run(runnables); 
} 

JFTR, no estoy diciendo que la segunda opción es "el" camino a seguir, es sólo que tener variables locales marcados como final antes de ser utilizado en las clases internas anónimas es un tema de oferta grande para mí. Por supuesto, YMMV. :-)

+0

Publiqué una versión descompilada de una clase interna anónima. Pero para ser sincero, todavía no veo por qué el compilador debe tener esa información. Incluso si el campo se declara final, el campo aún puede ser nulo. Creo que esta es una de esas peculiaridades de Java, tienes que declarar ese campo final ... porque así es como es. No hay una razón clara por qué. –

+0

@Berlin Brown: He actualizado la respuesta para abordar sus inquietudes, déjame saber si aún falta. –

0

También ayuda a comprender cómo crea Java una clase interna anónima. Cómo implementa Java esa clase en particular.

Java necesita que la variable sea definitiva porque el compilador debe conocer el tipo de ese objeto en tiempo de compilación. El compilador generará un campo dentro de la implementación anónima de la clase interna (en este caso 'et').

Si el tipo no es definitivo, ¿cómo determinaría el compilador cómo crear la implementación de la clase interna? Básicamente, al declarar el campo final, le está dando más información al compilador de Java.

Código que no ayuda a que el compilador, no se compilará la clase interna anónima:

Object et; 
et = a ? new Object() : new EditText(); 

...

Con el código anterior, el compilador Java no puede realmente construir el clase interna anónima.

su código:

final de EditarTexto et = (EditarTexto) findViewById (R.id.t);

...

new Button.OnClickListener$1(){ 
      public void onClick(View v)<br> 
      { 
      Intent on=new Intent(Intent.ACTION_CALL,Uri.parse("tel:"+et.getText())); 
      startActivity(on); 
      } 
     }); 

... El compilador Java creará una clase de código de bytes, una implementación de ese bloque clase interna que ya ha proporcionado que podría tener este aspecto.

public class OnClickListener$1 { 

private final EditText et ; <---- this is important 
public OnClickListener$1(final et) { 
    this.et = et; 
} 
public void onClick(View v)<br> 
       { 
       Intent on=new Intent(Intent.ACTION_CALL,Uri.parse("tel:"+et.getText())); 
       startActivity(on); 
       } 
} 

Puede probar el pseudo código que he proporcionado por la búsqueda de la clase de código de bytes anónimo $ 1 y descompilar el archivo de código de bytes.

1

El propósito de la palabra clave “final” en JAVA se puede definir en tres niveles son clase, método, variables

Java final variable: If you make any variable as final, you cannot change the value of final variable (It will be constant). 

Java final method: If you make any method as final, you cannot override it. 

Java final class: If you make any class as final, you cannot extend it. 
Cuestiones relacionadas