Lær Java for Android Development Mer om Inner Classes

Denne raske leksjonen diskuterer en rekke tips for å jobbe med indre klasser i Java. Denne leksjonen er en del av en kontinuerlig serie av opplæringsprogrammer for utviklere som lærer Java for å utvikle Android-applikasjoner.

Hva er (Anonym) Inner Klasser?

I Java kan klasser være nestet i hverandre for å organisere data og funksjonalitet på en ordnet måte. Anonyme indre klasser er i utgangspunktet utvikler stenografi, slik at utvikleren kan lage, definere og bruke et tilpasset objekt på en gang. Anonyme indre klasser brukes ofte i Android for å definere håndtere for kontroller, definere og starte nye tråder, og opprette og returnere egendefinerte objekter i metoder uten roteringskode med unødvendig oppsett.

For en grundig diskusjon om nestede og indre klasser, inkludert anonyme indre klasser, se vår veiledning kalt Learn Java for Android Development: Inner Classes

Å få tilgang til eksterne variabler med det endelige søkeordet

Noen ganger vil du få tilgang til informasjon tilgjengelig utenfor den indre klassen. Vurder følgende eksempel. Du har en skjerm med to kontroller: en knapp og en tekstvisning. Hver gang brukeren klikker på knappekontrollen, blir TextView-kontrollen oppdatert med gjeldende tid. Innen Aktivitetsklassen knyttet til dette oppsettet, er du kunne implementer denne funksjonaliteten som følger:

 Knapp myButton = (Button) findViewById (R.id.ButtonToClick); MyButton.setOnClickListener (new View.OnClickListener () public void onClick (Vis v) SimpleDateFormat formatter = ny SimpleDateFormat ("h: mm: ss a"); String strWhen = formatter.format (ny dato ()); TextView myTextview = (TextView) findViewById (R.id.TextViewToShow); myTextview.setText ("Clicked at" + strWhen);); 

Ovennevnte kode vil kjøre og oppføre seg som forventet. La oss imidlertid si at du virkelig ville deklarere TextView-kontrollen utenfor den indre klassen og bruke den til andre formål også. Kanskje du ville prøve å gjøre dette i stedet:

 TextView myTextview = (TextView) findViewById (R.id.TextViewToShow); Knapp myButton = (Button) findViewById (R.id.ButtonToClick); MyButton.setOnClickListener (new View.OnClickListener () public void onClick (Vis v) SimpleDateFormat formatter = ny SimpleDateFormat ("h: mm: ss a"); String strWhen = formatter.format (ny dato ()); myTextview. setText ("Clicked at" + strWhen);); 

Dessverre vil dette ikke kompilere. I stedet får du kompileringsfeilen "Kan ikke referere til en ikke-endelig variabel myTextview i en indre klasse definert i en annen metode". Som feilen antyder, er det nødvendig å gjøre TextView-variabelen endelig, slik at den er tilgjengelig i den indre klassens onClick () -metode:

 siste tekstvisning myTextview = (TextView) findViewById (R.id.TextViewToShow); Knapp myButton = (Button) findViewById (R.id.ButtonToClick); MyButton.setOnClickListener (new View.OnClickListener () public void onClick (Vis v) SimpleDateFormat formatter = ny SimpleDateFormat ("h: mm: ss a"); String strWhen = formatter.format (ny dato ()); myTextview. setText ("Clicked at" + strWhen);); 

Denne koden vil faktisk kompilere og løpe som forventet.

Arbeider med sluttvariabler i Java

Ved å gjøre TextView-variabelen endelig i det forrige eksempelet, har du gjort det tilgjengelig for den anonyme indre klassen (eller en hvilken som helst indre klasse som er definert innenfor sitt omfang, for den saks skyld). Her er noen andre ting å vite om sluttvariabler:

  • Du kan ikke endre verdien (r-verdien) for en endelig variabel. For eksempel, hvis du prøvde å tilordne myTextview-variabelen til en annen kontroll i metoden onClick () i den indre klassen, ville du få kompileringsfeilen "Den endelige lokale variabelen myTextview kan ikke tilordnes, siden den er definert i en omsluttende type. ”
  • Du kan ringe en metode for en endelig variabel, forutsatt at du har tilgang. Dette gjør det mulig for oss å ringe til TextViews setText () -metode. Dette endrer ikke verdien av variabelen myTextview, den endrer ganske enkelt det som vises på skjermen - en subtil men viktig forskjell. (Årsaken til dette er ganske enkelt at referansen til objektet ikke kan endres, men selve objektet kan forandre seg gjennom metodene.)
  • En endelig variabels verdi trenger ikke å være kjent ved kompileringstid, mens en statisk variabel er kjent ved kompileringstid.
  • Det endelige søkeordet er ofte sammenkoblet med den statiske variabelen (et felt eller en variabel knyttet til alle forekomster av en klasse, i stedet for en enkelt forekomst) for å lage en konstant for bruk i søknaden din, som i: offentlig statisk slutt String DEBUG_TAG, som brukes til LogCat-loggingsformål i hele aktiviteten din.

Inner klasser og "Denne" variabelen

I Java kan du bruke den spesielle dette referanse for å referere til den konkrete forekomsten av et objekt. Så hva skjer når du har en klasse med en indre klasse, eller, for den saks skyld, en anonym indre klasse? Vel, den indre klassen kan få tilgang til den spesielle denne forekomsten av den vedlagte klassen, og den har også denne referansen sin. For å få tilgang til denne forekomsten for den indre klassen, bruk bare denne syntaksen. For å få tilgang til denne forekomsten av den vedlagte klassen må du takke navnet på den vedlagte klassen, deretter en prikk, deretter dette. For eksempel:

 MyEnclosingClass.this 

Ta en titt på den fullstendige implementeringen av den anonyme indre klassen, som diskutert ovenfor, i full kontekst av sin omsluttende klasse, her kalt ClassChaosActivity:

 pakke com.androidbook.classchaos; importer java.text.SimpleDateFormat; importer java.util.Date; importer android.app.Activity; importere android.os.Bundle; importer android.util.Log; importer android.view.View; importer android.widget.Button; importer android.widget.TextView; offentlig klasse ClassChaosActivity utvider Aktivitet offentlig statisk endelig streng DEBUG_TAG = "MyLoggingTag"; / ** Kalt når aktiviteten er først opprettet. * / @Override public void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.main); siste tekstvisning myTextview = (TextView) findViewById (R.id.TextViewToShow); Knapp myButton = (Button) findViewById (R.id.ButtonToClick); MyButton.setOnClickListener (new View.OnClickListener () public void onClick (Vis v) SimpleDateFormat formatter = ny SimpleDateFormat ("h: mm: ss a"); String strWhen = formatter.format (ny dato ()); myTextview. setTxt ("Clicked at" + strWhen); Log.v (DEBUG_TAG, "dette klassenavnet:" + this.getClass (). getName ()); Log.v (DEBUG_TAG, "dette utvider grensesnittet heter:" + dette. GetClass (). getInterfaces () [0] .getName ()); Log.v (DEBUG_TAG, "dette Vedlegg klassenavn:" + this.getClass (). getEnclosingClass (). getName ()); Log.v (DEBUG_TAG , "Dette er anonym klasse?" + this.getClass () .AnonymousClass ()); Log.v (DEBUG_TAG, "ClassChaosActivity.this Klassenavn:" + ClassChaosActivity.this.getClass (). getName ()); Logg. v (DEBUG_TAG, "ClassChaosActivity.this Super Class navn:" + ClassChaosActivity.this.getClass (). getSuperclass (). getName ()); Log.v (DEBUG_TAG, "ClassChaosActivity.this Er anonym klasse?" + ClassChaosActivity.this .getClass (). isAnonymousClass ()););  

Loggutgangen for knappeklikk fortsetter som følger:

 10-24 18: 18: 53.075: VERBOSE / MyLoggingTag (751): dette klassenavnet: com.androidbook.classchaos.ClassChaosActivity $ 1 10-24 18: 18: 53,085: VERBOSE / MyLoggingTag (751): dette utvider grensesnittet heter: android .view.View $ OnClickListener 10-24 18: 18: 53.085: VERBOSE / MyLoggingTag (751): dette omsluttende klassenavn: com.androidbook.classchaos.ClassChaosActivity 10-24 18: 18: 53.095: VERBOSE / MyLoggingTag (751): dette er anonym klasse? True 10-24 18: 18: 53.095: VERBOSE / MyLoggingTag (751): ClassChaosActivity.this Klassenavn: com.androidbook.classchaos.ClassChaosAktivitet 10-24 18: 18: 53.105: VERBOSE / MyLoggingTag (751): ClassChaosActivity.this Super Klassenavn: android.app.Aktivitet 10-24 18: 18: 53.105: VERBOSE / MyLoggingTag (751): ClassChaosActivity.this Er anonym klasse? falsk 

Som du kan se, refererer dette søkeordet til den "nærmeste" klassen - den indre klassen. Selv om den indre klassen er anonym, gir Java det et antall ClassChaosActivity $ 1 for å holde rede på det. Selv om det ikke er nyttig for utviklere per se, viser dette at den anonyme indre klassen behandles som en annen klasse internt. I mellomtiden får vi tilgang til det vedlagte klassetilfellet ved hjelp av ClassChaosActivity.this syntaks.

Konklusjon

I denne raske leksjonen har du lært flere tips for å hjelpe deg med å bruke indre klasser og anonyme indre klasser mer dyktig. Du lærte at indre klasser kan få tilgang til variabler deklarert utenfor deres omfang, forutsatt at variablene er merket som endelige og derfor uforanderlige. Du har også lært om den spesielle syntaksen som er relatert til dette søkeordet når det gjelder tilgang til indre klasse-forekomstdata, samt omsluttelse av klasseeksemplardata.

Om forfatterne

Mobilutviklere Lauren Darcey og Shane Conder har medforfatter flere bøker om Android-utvikling: en grundig programmeringsbok med tittel Android Wireless Application Development og Sams TeachYourself Android Application Development i 24 timer. Når de ikke skriver, bruker de sin tid på å utvikle mobil programvare hos deres firma og tilby konsulenttjenester. De kan nås via e-post til [email protected], via bloggen deres på androidbook.blogspot.com, og på Twitter @androidwireless.

Trenger du flere hjelpeskrivende Android-apper? Se våre nyeste bøker og ressurser!