2016-04-21 15 views
2

Ich schreibe etwas Java-Code und in einem Moment wurde ich auf eine Sache blockiert.Cheat mit Java endgültigen Schlüsselwort

final String action = "action1"; 
final Button otherAction = (findById....); 
otherAction.setOnClickListener(new View.OnClickListener() { 
    @Override 
     public void onClick(View v) { 
      if (action.equals("action1")) { 
       action = "action2"; 
      } else if (action.equals("action2")) { 
       action = "action3"; 
      } else if (action.equals("action3")) { 
       action = "action1"; 
      } 
     } 
    }); 

Offensichtlich dieser Code funktioniert nicht, weil ich keinen neuen Wert zu action zuweisen kann, weil es eine endgültige Variable ist und so kann nur einmal initialisiert werden.
Um auf eine Variable innerhalb des onClickListener-Bereichs zuzugreifen, müssen Sie sie als final deklarieren.

Also, was ich tat, zu beheben ist:

final Button otherAction = (findById....); 
otherAction.setOnClickListener(new View.OnClickListener() { 
    @Override 
     public void onClick(View v) { 
      if (t.action.equals("action1")) { 
       t.action = "action2"; 
      } else if (t.action.equals("action2")) { 
       t.action = "action3"; 
      } else if (t.action.equals("action3")) { 
       t.action = "action1"; 
      } 
     } 
    }); 

Class t { 
    public static String action = "action1"; 
} 

Meine Frage ist: Warum ist das Arbeits?

+6

aus dem einfachen Grund - 't.action' ist nicht endgültig –

+2

anonyme innere Klassen können nur auf Variablen zugreifen, die effektiv final sind. Es wurde [hier im Detail erklärt] (http://stackoverflow.com/questions/4732544/why-are-only-final-variables-accessible-in-anonymous-class) – CarefreeCrayon

+1

@Raman Shrivastava Richtig, aber ich denke das Wesentliche der Frage des OP ist, warum nicht "t.action" endgültig sein muss, wenn es als eine 'public static'-Klassenvariable definiert ist, während es als final sein muss, wenn es nur eine lokale Variable ist. –

Antwort

3

Felder müssen nicht endgültig sein, um von anonymen Klassen aus zugegriffen zu werden, nur Methodenvariablen.

Dies ist, weil Feld (seiner Entität oder Klasse) existiert, bis es nicht mehr benötigt wird (bestimmt durch GC), so gibt es immer einen Platz, wo Sie zuweisen können.

Wenn Sie jedoch eine anonyme Klasseninstanz weitergeben, ist sie möglicherweise noch vorhanden, wenn die Methode exit enthalten ist. Stellen Sie sich vor, dass andereAction diese Hörer-Zeit in ferner Zukunft aufruft. Aber diese Variable kann nicht mehr zugewiesen werden, daher sollte sie endgültig sein und bei jeder Instanziierung beliebiger Klassen kopiert werden.

+0

Es war was ich vermutete, gute Antwort, danke – Lucsartes

0

Wie ich verstehe, funktioniert der 1. Codeblock nicht. Die "Arbeit" bedeutet hier: Kompilierungsfehler.

Die 2. funktioniert, weil wenn Java Language Specification folgt. Es gab keine Einschränkungen für nicht-lokale Parameter, formale Parameter. Die t.action ist eine statische Variable.

Any local variable, formal parameter, or exception parameter used but not declared in an inner class must be declared final. 

Any local variable used but not declared in an inner class must be definitely assigned (§16) before the body of the inner class. 

http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.1.3

Ein weiterer Hinweis ist, dass war vor Java 8. Java 8 führt das Konzept: effective Finale, das die lokalen Variablen wie oben für die innere Klasse verwendet werden, nicht offiziell deklariert werden müssen als Finale. Für weitere Einzelheiten kann es sehen: https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.1.3

Any local variable, formal parameter, or exception parameter used but not declared in an inner class must either be declared final or be **effectively** final (§4.12.4), or a compile-time error occurs where the use is attempted. 

mehr Erklärung über effektive Finale Siehe hier: Difference between final and effectively final

In Bezug auf, warum die zweite Codeblock funktioniert, können Sie hier lesen: Why are only final variables accessible in anonymous class?

Es ist die vernünftigste Antwort zu diesem Problem, das ich je gesehen habe :)

Verwandte Themen