Leer Java voor Android-ontwikkeling meer over innerlijke klassen

Deze korte les bespreekt een aantal tips voor het werken met innerlijke klassen op Java. Deze les maakt deel uit van een doorlopende reeks tutorials voor ontwikkelaars die Java leren om Android-applicaties te ontwikkelen.

Wat zijn (anonieme) innerlijke klassen?

In Java kunnen klassen in elkaar worden genest om gegevens en functionaliteit ordelijk te organiseren. Anonieme binnenklassen zijn in feite ontwikkelaars stenografisch, waardoor de ontwikkelaar in één keer een aangepast object kan maken, definiëren en gebruiken. Anonieme binnenklassen worden vaak gebruikt in Android om handlers voor besturingselementen te definiëren, nieuwe threads te definiëren en te starten en aangepaste objecten te maken en terug te sturen in methoden zonder rommelcode met onnodige instellingen.

Voor een grondige bespreking van geneste en innerlijke klassen, inclusief anonieme innerlijke klassen, zie onze tutorial Learn Java voor Android-ontwikkeling: Innerlijke klassen

Toegang tot externe variabelen met het definitieve sleutelwoord

Soms wil je toegang krijgen tot informatie die beschikbaar is buiten de innerlijke klasse. Bekijk het volgende voorbeeld. Je hebt een scherm met twee besturingselementen: een knop en een tekstweergave. Telkens wanneer de gebruiker op de knopbesturing klikt, wordt het TextView-besturingselement bijgewerkt met de huidige tijd. In de klasse Activiteit die aan deze lay-out is gekoppeld, jij kon implementeer deze functionaliteit als volgt:

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

De bovenstaande code wordt uitgevoerd en werkt zoals verwacht. Laten we echter zeggen dat u het TextView-besturingselement echt buiten de innerlijke klasse wilde verklaren en het ook voor andere doeleinden wilt gebruiken. Misschien zou je dit in plaats daarvan proberen te doen:

 TextView myTextview = (TextView) findViewById (R.id.TextViewToShow); Knop myButton = (Knop) findViewById (R.id.ButtonToClick); myButton.setOnClickListener (new View.OnClickListener () public void onClick (View v) SimpleDateFormat formatter = new SimpleDateFormat ("h: mm: ss a"); String strWhen = formatter.format (new Date ()); myTextview. setText ("Klikte op" + strWhen);); 

Helaas zal dit niet compileren. In plaats daarvan krijgt u de compileerfout "Kan niet verwijzen naar een niet-definitieve variabele myTextview binnen een innerlijke klasse die op een andere methode is gedefinieerd". Zoals de fout suggereert, moet u de TextView-variabele definitief maken, zodat deze toegankelijk is binnen de onClick () -methode van de inner class:

 final TextView myTextview = (TextView) findViewById (R.id.TextViewToShow); Knop myButton = (Knop) findViewById (R.id.ButtonToClick); myButton.setOnClickListener (new View.OnClickListener () public void onClick (View v) SimpleDateFormat formatter = new SimpleDateFormat ("h: mm: ss a"); String strWhen = formatter.format (new Date ()); myTextview. setText ("Klikte op" + strWhen);); 

Deze code zal inderdaad worden gecompileerd en uitgevoerd zoals verwacht.

Werken met eindvariabelen in Java

Door de TextView-variabele definitief te maken in het vorige voorbeeld, hebt u deze beschikbaar gemaakt voor de anonieme innerlijke klasse (of elke binnenklasse die binnen de scope ervan is gedefinieerd). Hier zijn nog enkele andere dingen die u moet weten over definitieve variabelen:

  • U kunt de waarde (r-waarde) van een laatste variabele niet wijzigen. Als u bijvoorbeeld probeert de variabele myTextview toe te wijzen aan een ander besturingselement binnen de onClick () -methode van de binnenklasse, krijgt u de compileerfout "De laatste lokale variabele myTextview kan niet worden toegewezen, omdat deze is gedefinieerd in een omhullend type. ”
  • Je kunt de methoden van een laatste variabele bellen, op voorwaarde dat je toegang hebt. Dit is wat ons in staat stelt om de methode setText () van TextView aan te roepen. Dit verandert de waarde van de variabele myTextview niet, het verandert eenvoudig wat wordt weergegeven op het scherm - een subtiel maar belangrijk verschil. (De reden hiervoor is eenvoudig dat de verwijzing naar het object niet kan veranderen, maar het object zelf kan veranderen door zijn methoden.)
  • De waarde van een laatste variabele hoeft niet bekend te zijn bij het compileren, terwijl een statische variabele bekend is tijdens het compileren.
  • Het laatste trefwoord wordt vaak gecombineerd met de statische variabele (een veld of variabele die is gekoppeld aan alle exemplaren van een klasse, in plaats van één exemplaar) om een ​​constante te maken voor gebruik binnen uw toepassing, zoals in: public statische finale String DEBUG_TAG, gebruikt voor LogCat-logboekdoeleinden tijdens uw activiteit.

Innerlijke klassen en de variabele "This"

In Java kun je de special gebruiken deze verwijzing om te verwijzen naar het specifieke exemplaar van een object. Dus wat gebeurt er als je een klas hebt met een innerlijke klasse, of, wat dat betreft, een anonieme innerlijke klasse? Welnu, de innerlijke klasse heeft toegang tot de speciale instantie van de omsluitende klasse, en deze heeft ook een eigen referentie. Gebruik de syntaxis om toegang te krijgen tot deze instantie voor de binnenklasse. Om toegang te krijgen tot de klasse van de omsluitende klasse, moet je eerst de naam van de insluitende klasse, dan een punt, dan dit. Bijvoorbeeld:

 MyEnclosingClass.this 

Bekijk de volledige implementatie van de anonieme innerlijke klasse, zoals hierboven besproken, in de volledige context van de omsluitende klasse, hier ClassChaosActivity genaamd:

 pakket com.androidbook.classchaos; importeer java.text.SimpleDateFormat; importeer java.util.Date; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.View; importeer android.widget.Button; import android.widget.TextView; public class ClassChaosActivity breidt activiteit uit public static final String DEBUG_TAG = "MyLoggingTag"; /** Opgeroepen wanneer de activiteit voor het eerst is gemaakt. * / @Override public void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.main); final TextView myTextview = (TextView) findViewById (R.id.TextViewToShow); Knop myButton = (Knop) findViewById (R.id.ButtonToClick); myButton.setOnClickListener (new View.OnClickListener () public void onClick (View v) SimpleDateFormat formatter = new SimpleDateFormat ("h: mm: ss a"); String strWhen = formatter.format (new Date ()); myTextview. setText ("Clicked at" + strWhen); Log.v (DEBUG_TAG, "this Class name:" + this.getClass (). getName ()); Log.v (DEBUG_TAG, "this extends interface named:" + this. getClass (). getInterfaces () [0] .getName ()); Log.v (DEBUG_TAG, "this Enclosing class name:" + this.getClass (). getEnclosingClass (). getName ()); Log.v (DEBUG_TAG , "this Is anonymous class?" + this.getClass (). isAnonymousClass ()); Log.v (DEBUG_TAG, "ClassChaosActivity.this Class name:" + ClassChaosActivity.this.getClass (). getName ()); Log. v (DEBUG_TAG, "ClassChaosActivity.this Super Class name:" + ClassChaosActivity.this.getClass (). getSuperclass (). getName ()); Log.v (DEBUG_TAG, "ClassChaosActivity.this Is anonymous class?" + ClassChaosActivity.this .getClass (). isAnonymousClass ()););  

De loguitvoer voor de knopklik verloopt als volgt:

 10-24 18: 18: 53.075: VERBOSE / MyLoggingTag (751): deze klassenaam: com.androidbook.classchaos.ClassChaosActivity $ 1 10-24 18: 18: 53.085: VERBOSE / MyLoggingTag (751): dit breidt de interface met de naam: android uit .view.View $ OnClickListener 10-24 18: 18: 53.085: VERBOSE / MyLoggingTag (751): deze insluitende klassenaam: com.androidbook.classchaos.ClassChaosActivity 10-24 18: 18: 53.095: VERBOSE / MyLoggingTag (751): dit is een anonieme les? true 10-24 18: 18: 53.095: VERBOSE / MyLoggingTag (751): ClassChaosActivity.this Class name: com.androidbook.classchaos.ClassChaosActivity 10-24 18: 18: 53.105: VERBOSE / MyLoggingTag (751): ClassChaosActivity.this Super Klasse naam: android.app.Activity 10-24 18: 18: 53.105: VERBOSE / MyLoggingTag (751): ClassChaosActivity.this Is anonymous class? vals 

Zoals je kunt zien, verwijst het alleen dit sleutelwoord naar de 'dichtstbijzijnde' klas, de innerlijke klasse. Hoewel de binnenklasse anoniem is, geeft Java het een nummer ClassChaosActivity $ 1 om het bij te houden. Hoewel dit op zich niet handig is voor ontwikkelaars, toont dit aan dat de anonieme innerlijke klasse intern wordt behandeld als elke andere klas. Ondertussen hebben we toegang tot de insluitende klasseninstantie met behulp van de classChaosActivity.deze syntaxis.

Conclusie

In deze korte les heb je verschillende tips geleerd om je te helpen om innerlijk en anonieme lessen beter te gebruiken. U hebt geleerd dat interne klassen toegang hebben tot variabelen die buiten hun bereik zijn verklaard, op voorwaarde dat de variabelen als definitief en daarom onveranderlijk zijn gemarkeerd. U hebt ook geleerd over de speciale syntaxis gerelateerd aan dit sleutelwoord als het gaat om toegang krijgen tot interne klasse-instantie-gegevens evenals de omsluitende klasseninstantie-gegevens.

Over de Auteurs

Mobiele ontwikkelaars Lauren Darcey en Shane Conder hebben samen meerdere boeken geschreven over Android-ontwikkeling: een diepgaand programmeerboek getiteld Android Wireless Application Development en Sams TeachYourself Android Application Development binnen 24 uur. Wanneer ze niet schrijven, besteden ze hun tijd aan het ontwikkelen van mobiele software bij hun bedrijf en het leveren van consultingservices. Ze zijn te bereiken via e-mail naar [email protected], via hun blog op androidbook.blogspot.com, en op Twitter @androidwireless.

Meer hulp nodig bij het schrijven van Android-apps? Bekijk onze nieuwste boeken en bronnen!