2012-07-03 25 views
8

Necesitaba cambiar variables dentro de una clase interna y recibí el infame error "No se puede referir a una variable no final dentro de una clase interna definida en un método diferente".clase interna variable no final java

void onStart(){ 
    bt.setOnClickListener(new View.OnClickListener() { 
    public void onClick(View v) { 
     int q = i; 
    } 
    }); 
} 

rápidamente me hizo una clase que celebra todas las cosas que quería cambiar e hizo una versión final de la clase fuera de la clase interna

class temp{ 
    int q; 
} 

void onStart(){ 
    final temp x = new temp(); 
    bt.setOnClickListener(new View.OnClickListener() { 
    public void onClick(View v) { 
     x.q = i; 
    } 
    }); 
} 

Esto parece ser lo que necesito y lo funciona, pero me pregunto si esta es la forma correcta de solucionar el problema. Además, realmente odio usar la palabra temp para nombrar mi clase. ¿Existe un término de programación real para lo que hice para que haga un nombre más descriptivo para mi clase?

Respuesta

9

Puede simplemente crear una clase interna en lugar de anónima (como lo hace actualmente). Luego tienes un constructor y cualquier otro método que quieras establecer para tus miembros. No se requiere hackiness (como la matriz de 1 caso).

Encuentro este limpiador si la clase requiere algún intercambio de datos con su clase externa, pero admito que es una preferencia personal. El conjunto de 1 modismo funcionará también y es más escueto, pero, francamente, se ve mal. Normalmente limito las clases internas anónimas a aquellas que solo realizan acciones sin intentar actualizar los datos en la clase externa.

Por ejemplo:

private MyListener listener = new MyListener(); 

void onStart(){ 
    bt.setOnClickListener(listener); 
} 

class MyListener implements OnClickListener 
{ 
    String name; 
    int value; 

    void setName(String newName) 
    { 
     name = newName; 
    } 

    void setValue(int newValue) 
    { 
     value = newValue; 
    } 

    public void onClick(View v) 
    { 
     // Use the data for some unknown purpose 
    } 
} 

Si hay varios subprocesos implicados, a continuación, la sincronización adecuada tendrá que ser utilizado también.

+0

Bravo. La otra cosa agradable es que esta clase interna es más extensible y reutilizable. IMO, las clases internas anónimas son casi siempre una mala idea. – user949300

+0

Funcionan bien como clases de estilo de acción única, controladores para eventos específicos en los que las acciones se pueden realizar en función de las entradas. Muy común en la programación de GUI, que es su ejemplo. Excepto en este caso, existe esa interacción entre las clases que complica las cosas. – Robin

+0

¡Esto es lo que estaba buscando! ¡Gracias! –

2

Publiqué una respuesta similar en mi other thread here. Básicamente, la idea es crear una "envoltura" que se ajuste prácticamente a cualquier tipo de Object. Dado que final en Java significa "sin reasignación" y no "constante", este truco funciona bastante bien. Pero como se mencionó en la publicación original, asegúrese de pisar con precaución cuando lo utilice en un entorno con múltiples subprocesos.

0

Me gustaría mantener una referencia a su oyente clic en la clase externa, y hacer que el int una variable miembro en su oyente. Simplemente almacene la variable en el oyente al hacer clic, luego tome la variable en la clase externa cuando la necesite, en lugar de configurarla en el momento del clic.

Para decirlo simplemente, si la clase interna necesita cambiarlo, hágalo una variable en la clase interna.

0

Dado que parece que está configurando varias cosas (a partir de los comentarios), haga un método en la clase principal, button1WasClicked(), (un nombre mejor podría ser doUpdate, doSave etc. - algo relevante para lo que hace el botón), ponga el código correcto allí, y llámalo de la clase/oyente interno. (Si está utilizando Swing, lo convertiría en una Acción, YMMV)

De esta manera si más adelante hay un menú o un intento o un gesto que necesita ejecutar el mismo material, la llamada está allí.

Cuestiones relacionadas