Programmering

Hvordan lagre data i Java-objekter

Sist oppdatert: januar 2020

Selv om snooze-knappen sannsynligvis er den mest brukte knappen på en vekkerklokke, til og med en enkel Vekkerklokke klassen trenger noen flere funksjoner. Det kan for eksempel være lurt å kontrollere hvor lenge vekkerklokken skal være i slumringsmodus. For å legge til en slik funksjon, må du forstå hvordan Java styrer data.

Utviklere bruker variabler i Java for å holde data, med alle variabler som har en datatype og et navn. Datatypen bestemmer verdiene som en variabel kan inneholde. I denne opplæringen lærer du hvordan integrerte typer inneholder hele tall, flytende punkttyper inneholder reelle tall, og strengtyper inneholder tegnstrenger. Så kommer du i gang med å bruke instansvariabler i Java-klassene dine.

Variabler og primitive typer

Kalt primitive typer, integrerte og flytende punkttyper er de enkleste datatypene i Java. Følgende program illustrerer den integrerte typen, som kan inneholde både positive og negative heltall. Dette programmet illustrerer også kommentarer, som dokumenterer koden din, men ikke påvirker programmet på noen måte.

/ * * Dette er også en kommentar. Kompilatoren ignorerer alt fra * den første / * til en "stjerne skråstrek" som avslutter kommentaren. * * Her er "stjerneskråningen" som avslutter kommentaren. * / public class IntegerTest {public static void main (String [] args) {// Her er erklæringen om en int-variabel kalt anInteger, // som du gir en startverdi på 100. int anInteger = 100; // Deklarere og initialisere et heltall System.out.println (et heltall); // Utganger 100 // Du kan også gjøre aritmetikk med primitive typer ved å bruke // standard aritmetiske operatorer. et heltall = 100 + 100; System.out.println (et heltall); // Utganger 200}} 

Java bruker også flytende punkttyper, som kan inneholde reelle tall, noe som betyr tall som inkluderer en desimal. Her er et eksempel på program:

public class DoubleTest {public static void main (String [] args) {// Her er erklæringen om en dobbel variabel kalt aDouble. // Du gir også aDouble en startverdi på 5,76. dobbelt aDobbelt = 5,76; // Deklarere og initialisere aDouble System.out.println (aDouble); // Outputs 5.76 // Du kan også gjøre regning med flytende punkttyper. aDobbelt = 5,76 + 1,45; System.out.println (aDouble); // Utganger 7.21}} 

Prøv å kjøre programmene ovenfor. Husk at du må kompilere før du kan kjøre dem:

javac * .java java IntegerTest java DoubleTest 

Java bruker fire integrerte typer og to flytende punkttyper, som begge har forskjellige tallområder og tar forskjellige mengder lagringsplass, som vist i tabellene nedenfor.

Integrerte typer

TYPEByteKortIntLang
STØRRELSE (bits)8163264
OMRÅDE-128 til 127-32 768 til 32 767-2,147,483,648 til 2,147,483,647-263 til 263-1

Flytpunkttyper (IEEE 754-format)

 
TYPEFlytende punkt med en presisjonDobbelt presisjon flytende punkt
STØRRELSE (bits)3264
OMRÅDE+/- 1.18x10-38 til +/- 3.4x1038+/- 2.23x10-308 til +/- 1.8x10308

EN streng type holder på strenger og håndterer dem annerledes enn måten integrerte og flytende punkttyper håndterer tall på. Java-språket inkluderer en String klasse for å representere strenger. Du erklærer en streng ved hjelp av typen String, og initialiser den med en sitert streng, en sekvens av tegn inneholdt i dobbelt anførselstegn, som vist nedenfor. Du kan også kombinere to strenger ved hjelp av + operatør.

// Kodefragment // Erklæring om variabler s av typen String, // og initialisering med sitert streng "Hei." String s = "Hei"; // Sammenkobling av streng i s med sitert streng "Verden" String t = s + "Verden"; System.out.println (t); // Utganger Hei Verden

Variabelt omfang

I tillegg til typen, omfang er også et viktig kjennetegn ved en variabel. Scope etablerer når en variabel opprettes og ødelegges, og hvor en utvikler kan få tilgang til variabelen i et program. Stedet i programmet der du erklærer variabelen, bestemmer omfanget.

Så langt har jeg diskutert lokale variabler, som inneholder midlertidige data som du bruker i en metode. Du erklærer lokale variabler i metoder, og du kan bare få tilgang til dem innenfor disse metodene. Dette betyr at du bare kan hente lokale variabler et heltall, som du brukte i IntegerTest, og aDobbelt, som du brukte i DoubleTest, fra hovedmetoden der de ble erklært og ingen andre steder.

Du kan erklære lokale variabler innen hvilken som helst metode. Eksempelkoden nedenfor erklærer en lokal variabel i AlarmClock slumrer () metode:

offentlig klasse AlarmClock {public void snooze () {// Snooze time in millisecond = 5 secs long snoozeInterval = 5000; System.out.println ("ZZZZZ for:" + snoozeInterval); }} 

Du kan komme til snoozeInterval bare fra slumre () metoden, som er der du erklærte snoozeInterval, som vist her:

offentlig klasse AlarmClockTest {public static void main (String [] args) {AlarmClock aClock = new AlarmClock (); aClock.snooze (); // Dette er fortsatt greit. // Neste kodelinje er en FEIL. // Du får ikke tilgang til snoozeInterval utenfor snooze-metoden. snoozeInterval = 10000; }} 

Metodeparametere

EN metodeparameter, som har et omfang som ligner på en lokal variabel, er en annen type variabel. Metodeparametere overfører argumenter til metoder. Når du erklærer metoden, spesifiserer du argumentene i en parameterliste. Du sender argumentene når du kaller metoden. Metodeparametere fungerer på samme måte som lokale variabler ved at de ligger innenfor omfanget av metoden de er knyttet til, og kan brukes gjennom hele metoden. I motsetning til lokale variabler får metodeparametere imidlertid en verdi fra den som ringer når den kaller en metode. Her er en modifikasjon av vekkerklokken som lar deg passere i snoozeInterval.

offentlig klasse AlarmClock {public void snooze (long snoozeInterval) {System.out.println ("ZZZZZ for:" + snoozeInterval); }} 
offentlig klasse AlarmClockTest {public static void main (String [] args) {AlarmClock aClock = new AlarmClock (); // Pass i slumreintervallet når du kaller metoden. aClock.snooze (10000); // Utsett i 10000 ms. }} 

Medlemsvariabler: Hvordan objekter lagrer data

Lokale variabler er nyttige, men fordi de bare gir midlertidig lagring, er verdien begrenset. Siden levetiden strekker seg over lengden på metoden de blir deklarert i, sammenlignes lokale variabler med et notisblokk som vises hver gang du mottar en telefonsamtale, men forsvinner når du legger på. Det oppsettet kan være nyttig for å notere notater, men noen ganger trenger du noe mer permanent. Hva skal en programmerer gjøre? Tast inn medlemsvariabler.

Medlemsvariabler - hvorav det er to, forekomst og statisk - utgjør en del av en klasse.

Variabelt omfang og levetid

Utviklere implementerer forekomstvariabler for å inneholde data som er nyttige for en klasse. En forekomstvariabel skiller seg fra en lokal variabel med hensyn til omfanget og levetiden. Hele klassen utgjør omfanget av en forekomstvariabel, ikke metoden den ble deklarert i. Med andre ord, utviklere kan få tilgang til forekomstvariabler hvor som helst i klassen. I tillegg er levetiden til en forekomstvariabel ikke avhengig av noen bestemt metode i klassen; det vil si at levetiden er levetiden til den forekomsten som inneholder den.

Forekomster er de faktiske objektene du lager fra tegningen du designer i klassedefinisjonen. Du erklærer forekomstvariabler i klassedefinisjonen, og påvirker hver forekomst du oppretter fra tegningen. Hver forekomst inneholder disse forekomstvariablene, og data som holdes i variablene kan variere fra forekomst til forekomst.

Vurder Vekkerklokke klasse. Passerer snoozeInterval inn i det slumre () metoden er ikke et flott design. Tenk deg å måtte skrive inn et slumreintervall på vekkerklokken hver gang du fomlet etter snooze-knappen. I stedet er det bare å gi hele vekkerklokken a snoozeInterval. Du fullfører dette med en forekomstvariabel i Vekkerklokke klasse, som vist nedenfor:

offentlig klasse AlarmClock {// Du erklærer snoozeInterval her. Dette gjør det til en forekomstvariabel. // Du initialiserer det også her. lang m_snoozeInterval = 5000; // Utsett tid i millisekunder = 5 sekunder. public void snooze () {// Du kan fortsatt komme til m_snoozeInterval i en AlarmClock-metode // fordi du er innenfor klassen. System.out.println ("ZZZZZ for:" + m_snoozeInterval); }} 

Du kan få tilgang til forekomstvariabler nesten hvor som helst i klassen som erklærer dem. For å være teknisk om det, erklærer du forekomstvariabelen i klasses omfang, og du kan hente den fra nesten hvor som helst innenfor det omfanget. Praktisk sett har du tilgang til variabelen hvor som helst mellom den første krøllete braketten som starter klassen og den lukkende braketten. Siden du også deklarerer metoder innenfor klassens omfang, kan også de få tilgang til forekomstvariablene.

Du kan også få tilgang til forekomstvariabler utenfor klassen, så lenge en forekomst eksisterer, og du har en variabel som refererer til forekomsten. For å hente en forekomstvariabel gjennom en forekomst, bruker du prikkoperatør sammen med forekomsten. Det er kanskje ikke den ideelle måten å få tilgang til variabelen, men for nå, fullfør den på denne måten for illustrative formål:

public class AlarmClockTest {public static void main (String [] args) {// Lag to klokker. Hver har sin egen m_snoozeInterval AlarmClock aClock1 = ny AlarmClock (); AlarmClock aClock2 = ny AlarmClock (); // Endre aClock2 // Du vil snart se at det er mye bedre måter å gjøre dette på. aClock2.m_snoozeInterval = 10000; aClock1.snooze (); // Slumre med aClock1s intervall aClock2.snooze (); // Slumre med aClock2s intervall}} 

Prøv dette programmet, så ser du det aKlokke1 har fortsatt sitt intervall på 5000 mens aKlokke2 har et intervall på 10 000. Igjen, hver forekomst har sine egne forekomstdata.

Ikke glem, klassedefinisjonen er bare en blåkopi, så forekomstvariablene eksisterer faktisk ikke før du oppretter forekomster fra planen. Hver forekomst av en klasse har sin egen kopi av forekomstvariablene, og tegningen definerer hva disse forekomstvariablene vil være.

JavaWorld

Innkapsling

Innkapsling er en av grunnlagene for objektorientert programmering. Når du bruker innkapsling, samhandler brukeren med typen gjennom den eksponerte atferden, ikke direkte med den interne implementeringen. Gjennom innkapsling skjuler du detaljene for implementeringen av en type. I Java oversetter innkapsling i utgangspunktet til denne enkle retningslinjen: "Ikke få tilgang til objektets data direkte, bruk metodene."

Det er en elementær ide, men det letter livet vårt som programmerere. Tenk deg for eksempel at du ønsket å instruere en Person motstand mot å stå opp. Uten innkapsling kan kommandoene dine gå omtrent slik: "Vel, jeg antar at du må stramme denne muskelen her foran på benet, løsne denne muskelen her på baksiden av beinet. Hmmm - trenger å bøye seg ved livet også. Hvilke muskler gnister den bevegelsen? Trenger du å stramme disse, løsne dem. Whoops! Glemte det andre benet. Darn. Se på det - ikke velte ... "Du får ideen. Med innkapsling trenger du bare å påkalle stå opp() metode. Ganske enkelt, ja?

Noen fordeler med innkapsling:

  • Abstraksjon av detaljer: Brukeren samhandler med en type på et høyere nivå. Hvis du bruker stå opp() metoden, trenger du ikke lenger å kjenne alle musklene som kreves for å starte den bevegelsen.
  • Isolasjon fra endringer:Endringer i intern implementering påvirker ikke brukerne. Hvis en person forstuver en ankel, og er avhengig av en stokk en stund, bruker brukerne fortsatt barestå opp()metode.
  • Korrekthet:Brukere kan ikke endre innsiden av et objekt vilkårlig. De kan bare fullføre det du tillater dem å gjøre i metodene du skriver.

Her er et kort eksempel der innkapsling tydelig hjelper i programmets nøyaktighet:

// Dårlig - bruker ikke innkapsling offentlig klasse Person {int m_age; } offentlig klasse PersonTest {public static void main (String [] args) {Person p = new Person (); p.m_age = -5; // Hei - hvordan kan noen være minus 5 år? }} // Bedre - bruker innkapsling offentlig klasse Person {int m_age; public void setAge (int age) {// Sjekk for å sikre at alderen er høyere enn 0. Jeg snakker mer om // if uttalelser på et annet tidspunkt. hvis (alder> 0) {m_age = alder; }}} offentlig klasse PersonTest {public static void main (String [] args) {Person p = new Person (); p.setAge (-5); // Vil ikke ha noen effekt nå. }} 

Selv det enkle programmet viser hvordan du kan komme i trøbbel hvis du får direkte tilgang til interne data fra klasser. Jo større og mer komplekst programmet er, desto viktigere blir innkapslingen. Husk også at mange programmer begynner i det små og deretter varer til ubestemt tid, så det er viktig at du designer dem riktig, helt fra begynnelsen. Å bruke innkapsling på Vekkerklokke, kan du bare lage metoder for å manipulere slumreintervallet.

Et notat om metoder

Metoder kan returnere verdier som innringeren bruker. For å returnere en verdi, erklær en ikke-ugyldig returtype, og bruk en komme tilbake uttalelse. De getSnoozeInterval () metoden vist i eksemplet nedenfor illustrerer dette.

Skriv programmet

$config[zx-auto] not found$config[zx-overlay] not found