Această lecție rapidă discută o serie de sfaturi pentru a lucra cu clase interioare în Java. Această lecție face parte dintr-o serie continuă de tutoriale pentru dezvoltatorii care învață Java pentru a dezvolta aplicații Android.
În Java, clasele pot fi imbricate între ele pentru a organiza datele și funcționalitatea în mod ordonat. Clasele interioare anonime sunt în esență stenograma dezvoltatorului, permițând dezvoltatorului să creeze, să definească și să utilizeze un obiect particularizat într-un singur pas. Clasele interioare anonime sunt utilizate frecvent în Android pentru a defini utilizatorii de comenzi pentru control, pentru a defini și a lansa fire noi și pentru a crea și a readuce obiecte personalizate în metode, fără a fi aglomerat codul cu setări inutile.
Pentru o discuție aprofundată a claselor imbricate și a celor interioare, inclusiv clase de anonime, vedeți tutorialul nostru, numit Learn Java for Android Development: Classes Inner
Uneori doriți să accesați informațiile disponibile în afara clasei interioare. Luați în considerare următorul exemplu. Aveți un ecran cu două comenzi: un Buton și un TextView. De fiecare dată când utilizatorul face clic pe butonul de comandă, controlul TextView este actualizat cu ora curentă. În cadrul clasei de activitate asociate acestui aspect, tu ar putea implementați această funcție după cum urmează:
Butonul myButton = (butonul) findViewById (R.id.ButtonToClick); myButton.setOnClickListener (new View.OnClickListener () public void onClick (Vizualizare v) SimpleDateFormat formatter = new SimpleDateFormat ("h: mm: ss a"); = (TextView) findViewById (R.id.TextViewToShow); myTextview.setText ("Apasat la" + strWhen););
Codul de mai sus va funcționa și se va comporta conform așteptărilor. Cu toate acestea, să presupunem că ați vrut cu adevărat să declarați controlul TextView în afara clasei interioare și să îl utilizați și în alte scopuri. Poate că ați încerca să faceți acest lucru în schimb:
TextView myTextView = (TextView) findViewById (R.id.TextViewToShow); Butonul myButton = (butonul) findViewById (R.id.ButtonToClick); myButton.setOnClickListener (noul View.OnClickListener () public void onClick (Vizualizare v) SimpleDateFormat formatter = nou SimpleDateFormat ("h: mm: ss a") String strWhen = formatter.format (new Date); setText ("Apăsat la" + strWhen););
Din păcate, acest lucru nu se va compila. În schimb, veți obține eroarea de compilare "Nu mă pot referi la o variabilă non-finală myTextview într-o clasă interioară definită printr-o metodă diferită". Așa cum sugerează eroarea, ceea ce trebuie să faceți este să faceți ca variabila TextView să fie finală, astfel încât să fie accesibilă în cadrul metodei onClick () din clasa interioară:
definitiv TextView myTextview = (TextView) findViewById (R.id.TextViewToShow); Butonul myButton = (butonul) findViewById (R.id.ButtonToClick); myButton.setOnClickListener (noul View.OnClickListener () public void onClick (Vizualizare v) SimpleDateFormat formatter = nou SimpleDateFormat ("h: mm: ss a") String strWhen = formatter.format (new Date); setText ("Apăsat la" + strWhen););
Acest cod va fi într-adevăr compilat și executat conform așteptărilor.
Prin transformarea finală a variabilei TextView în exemplul anterior, l-ați pus la dispoziția clasei interioare anonime (sau a oricărei clase interioare definite în domeniul său de aplicare, de pildă). Iată câteva alte lucruri de știut despre variabilele finale:
În Java, puteți utiliza funcția specială acest trimitere la referință la instanța specifică a unui obiect. Deci, ce se întâmplă atunci când aveți o clasă cu o clasă interioară sau, de altfel, o clasă anonimă interioară? Ei bine, clasa interioară poate accesa această specialitate a clasei închise și are o referință proprie. Pentru a accesa această instanță pentru clasa interioară, pur și simplu utilizați această sintaxă. Pentru a accesa această instanță a clasei de închidere, trebuie să faceți clic pe numele clasei închise, apoi pe un punct, apoi pe acesta. De exemplu:
MyEnclosingClass.this
Aruncați o privire la implementarea completă a clasei interioare anonime, așa cum sa discutat mai sus, în contextul integral al clasei sale închise, numită aici ClassChaosActivity:
pachet com.androidbook.classchaos; import java.text.SimpleDateFormat; import java.util.Date; importă android.app.Activity; import android.os.Bundle; import șiroid.util.Log; import șiroid.view.View; import șiroid.widget.Button; import șiroid.widget.TextView; clasa publica ClassChaosActivity se extinde Activitatea String final public static DEBUG_TAG = "MyLoggingTag"; / ** Chemată când se creează prima activitate. * / @Override publică void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.main); definitiv TextView myTextview = (TextView) findViewById (R.id.TextViewToShow); Butonul myButton = (butonul) findViewById (R.id.ButtonToClick); myButton.setOnClickListener (noul View.OnClickListener () public void onClick (Vizualizare v) SimpleDateFormat formatter = nou SimpleDateFormat ("h: mm: ss a") String strWhen = formatter.format (new Date); setText ("Apăsat la" + strWhen); Log.v (DEBUG_TAG, "acest nume de clasă:" + this.getClass () getName ()); getClass () getInterfaces () [0] .getName ()); Log.v (DEBUG_TAG, "acest nume de clasă închis:" + this.getClass () getEnclosingClass , "aceasta este o clasă anonimă" + this.getClass () esteAnonymousClass ()); Log.v (DEBUG_TAG, "ClassChaosActivity.this Denumirea clasei:" + ClassChaosActivity.this.getClass () getName ()); v (DEBUG_TAG, "ClassChaosActivity.this este o clasă anonimă" + ClassChaosActivity.this (DEBUG_TAG, "ClassChaosActivity.this este o clasă anonimă") + ClassChaosActivity.this.getClass () .getClass () esteAnonymousClass ()););
Ieșirea jurnalului pentru clic pe buton continuă după cum urmează:
10-24 18: 18: 53.075: VERBOSE / MyLoggingTag (751): această clasă nume: com.androidbook.classchaos.ClassChaosActivity $ 1 10-24 18: 18: 53.085: VERBOSE / MyLoggingTag .view.View $ OnClickListener 10-24 18: 18: 53.085: VERBOSE / MyLoggingTag (751): acest nume de clasă închis: com.androidbook.classchaos.ClassChaosActivity 10-24 18: 18: 53.095: VERBOSE / MyLoggingTag (751): aceasta este clasa anonimă? true 10-24 18: 18: 53.095: VERBOSE / MyLoggingTag (751): ClassChaosActivity.this Numele clasei: com.androidbook.classchaos.ClassChaosActivity 10-24 18: 18: 53.105: VERBOSE / MyLoggingTag (751): ClassChaosActivity.this Super Numele clasei: android.app.Activity 10-24 18: 18: 53.105: VERBOSE / MyLoggingTag (751): ClassChaosActivity.This este o clasă anonimă? fals
După cum puteți vedea, acest cuvânt cheie se referă singură la clasa "cea mai apropiată" - clasa interioară. Deși clasa interioară este anonimă, Java îi dă un număr de $ 1 pentru a urmări acest lucru. Deși nu este util dezvoltatorilor per se, acest lucru arată că clasa anonimă internă este tratată ca orice altă clasă internă. Între timp, accesăm instanța de clasă care se închide folosind sintaxa ClassChaosActivity.this.
În această lecție rapidă ați învățat câteva sfaturi pentru a vă ajuta să utilizați clase interioare și clase interioare anonime cu mai multă îndemânare. Ați învățat că clasele interioare pot accesa variabilele declarate în afara domeniului lor de aplicare, cu condiția ca variabilele să fie marcate ca fiind finale și, prin urmare, neschimbate. De asemenea, ați aflat despre sintaxa specială legată de acest cuvânt cheie atunci când vine vorba de accesarea datelor de instanță de clasă interioară,.
Dezvoltatorii mobili Lauren Darcey și Shane Conder au coautorizat mai multe cărți despre dezvoltarea Android: o carte de programare în profunzime intitulată Dezvoltarea aplicațiilor fără fir Android și Sams TeachYourself Dezvoltarea de aplicații Android în 24 de ore. Când nu scriu, își petrec timpul dezvoltând software-ul mobil la compania lor și oferind servicii de consultanță. Acestea pot fi obținute prin e-mail la androidwirelessdev@[email protected], prin intermediul blogului lor la androidbook.blogspot.com, și pe Twitter @ androidwireless.