Programmering

Sådan gemmes data i Java-objekter

Sidst opdateret: januar 2020

Selvom snooze-knappen sandsynligvis er den mest almindelige knap på et vækkeur, endda en simpel Vækkeur klasse har brug for et par flere funktioner. For eksempel vil du måske kontrollere, hvor længe vækkeuret forbliver i slumretilstand. For at tilføje en sådan funktion skal du forstå, hvordan Java styrer data.

Udviklere bruger variabler i Java for at holde data, hvor alle variabler har en datatype og et navn. Datatypen bestemmer de værdier, som en variabel kan indeholde. I denne vejledning lærer du, hvordan integraltyper holder hele tal, flydende punkttyper indeholder reelle tal, og strengetyper indeholder tegnstrenge. Derefter kommer du i gang med at bruge instansvariabler i dine Java-klasser.

Variabler og primitive typer

Hedder primitive typer, integrerede og flydende punkttyper er de enkleste datatyper i Java. Det følgende program illustrerer integraltypen, som kan rumme både positive og negative heltal. Dette program illustrerer også kommentarer, der dokumenterer din kode, men ikke påvirker programmet på nogen måde.

/ * * Dette er også en kommentar. Compileren ignorerer alt fra * den første / * indtil en "stjerne skråstreg", som afslutter kommentaren. * * Her er "stjerneskråning", der afslutter kommentaren. * / public class IntegerTest {public static void main (String [] args) {// Her er erklæringen om en int-variabel kaldet anInteger, // som du giver en startværdi på 100. int anInteger = 100; // Erklære og initialisere et heltal System.out.println (et heltal); // Outputs 100 // Du kan også gøre aritmetik med primitive typer ved hjælp af // standard aritmetiske operatorer. et heltal = 100 + 100; System.out.println (anInteger); // Outputs 200}} 

Java bruger også flydende punkttyper, som kan rumme reelle tal, hvilket betyder tal, der inkluderer en decimal. Her er et eksempel på et program:

public class DoubleTest {public static void main (String [] args) {// Her er erklæringen om en dobbelt variabel kaldet aDouble. // Du giver også aDouble en indledende værdi på 5,76. dobbelt aDobbelt = 5,76; // Erklære og initialisere aDouble System.out.println (aDouble); // Outputs 5.76 // Du kan også regne med flydende punkttyper. aDobbelt = 5,76 + 1,45; System.out.println (aDouble); // Udgange 7.21}} 

Prøv at køre ovenstående programmer. Husk, du skal kompilere, før du kan køre dem:

javac * .java java IntegerTest java DoubleTest 

Java bruger fire integraltyper og to flydende punkttyper, som begge har forskellige talintervaller og optager forskellige mængder lagerplads, som vist i nedenstående tabeller.

Integrerede typer

TYPEByteKortIntLang
STØRRELSE (bits)8163264
RÆKKEVIDDE-128 til 127-32,768 til 32,767-2,147,483,648 til 2,147,483,647-263 til 263-1

Flydepunkttyper (IEEE 754-format)

 
TYPEFlydende punkt med en enkelt præcisionDobbeltpræcisions flydepunkt
STØRRELSE (bits)3264
RÆKKEVIDDE+/- 1.18x10-38 til +/- 3.4x1038+/- 2.23x10-308 til +/- 1.8x10308

EN streng type holder strenge og håndterer dem forskelligt fra den måde, hvorpå integrerede og flydende punkter håndterer tal. Java-sproget inkluderer en Snor klasse til at repræsentere strenge. Du erklærer en streng ved hjælp af typen Snor, og initialiser den med en citeret streng, en sekvens af tegn indeholdt i dobbelt anførselstegn, som vist nedenfor. Du kan også kombinere to strenge ved hjælp af + operatør.

// Kodefragment // Erklæring om variable s af typen String, // og initialisering med citeret streng "Hej". String s = "Hej"; // Sammenkædning af streng i s med citeret streng "Verden" Streng t = s + "Verden"; System.out.println (t); // Udgange Hej Verden

Variabelt omfang

Ud over typen, rækkevidde er også en vigtig egenskab ved en variabel. Scope fastslår, hvornår en variabel oprettes og destrueres, og hvor en udvikler kan få adgang til variablen i et program. Det sted i dit program, hvor du erklærer variablen, bestemmer dens omfang.

Indtil videre har jeg diskuteret lokale variabler, som indeholder midlertidige data, som du bruger inden for en metode. Du erklærer lokale variabler inden for metoder, og du kan kun få adgang til dem inden for disse metoder. Dette betyder, at du kun kan hente lokale variabler et heltal, som du brugte i IntegerTestog aDobbelt, som du brugte i DoubleTest, fra den vigtigste metode, hvori de blev erklæret, og ingen andre steder.

Du kan erklære lokale variabler inden for enhver metode. Eksempelkoden nedenfor erklærer en lokal variabel i AlarmClock udsætter () metode:

offentlig klasse AlarmClock {public void snooze () {// Udsæt tid i millisekund = 5 sekunder lang snoozeInterval = 5000; System.out.println ("ZZZZZ for:" + snoozeInterval); }} 

Du kan komme til snoozeInterval kun fra udsætte () metode, hvor du erklærede snoozeInterval, som vist her:

offentlig klasse AlarmClockTest {public static void main (String [] args) {AlarmClock aClock = new AlarmClock (); aClock.snooze (); // Dette er stadig fint. // Den næste linje kode er en FEJL. // Du kan ikke få adgang til snoozeInterval uden for snooze-metoden. snoozeInterval = 10000; }} 

Metodeparametre

EN metode parameter, som har et omfang svarende til en lokal variabel, er en anden type variabel. Metodeparametre overfører argumenter til metoder. Når du erklærer metoden, angiver du dens argumenter i en parameterliste. Du sender argumenterne, når du kalder metoden. Metodeparametre fungerer på samme måde som lokale variabler, idet de ligger inden for omfanget af den metode, som de er knyttet til, og kan bruges i hele metoden. Men i modsætning til lokale variabler får metodeparametre en værdi fra den, der ringer op, når den kalder en metode. Her er en ændring af vækkeuret, der giver dig mulighed for at 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 (); // Giv snooze-intervallet, når du kalder metoden. aClock.snooze (10000); // Udsæt i 10000 ms. }} 

Medlemsvariabler: Hvordan objekter gemmer data

Lokale variabler er nyttige, men fordi de kun giver midlertidig lagring, er deres værdi begrænset. Da deres levetid spænder over længden af ​​den metode, hvori de erklæres, sammenlignes lokale variabler med et notesblok, der vises hver gang du modtager et telefonopkald, men forsvinder, når du lægger på. Denne opsætning kan være nyttig til at notere noter, men nogle gange har du brug for noget mere permanent. Hvad skal en programmør gøre? Gå ind medlemsvariabler.

Medlemsvariabler - hvoraf der er to, eksempel og statisk - udgør en del af en klasse.

Variabelt omfang og levetid

Udviklere implementerer instansvariabler for at indeholde data, der er nyttige for en klasse. En instansvariabel adskiller sig fra en lokal variabel med hensyn til dens omfang og dens levetid. Hele klassen udgør omfanget af en instansvariabel, ikke den metode, hvori den blev deklareret. Med andre ord kan udviklere få adgang til instansvariabler hvor som helst i klassen. Derudover afhænger levetiden for en instansvariabel ikke af nogen bestemt metode i klassen; det vil sige, dets levetid er levetiden for den instans, der indeholder den.

Tilfælde er de egentlige objekter, du opretter fra den tegning, du designer i klassedefinitionen. Du erklærer instansvariabler i klassedefinitionen, der påvirker hver forekomst, du opretter fra planen. Hver forekomst indeholder disse instansvariabler, og data indeholdt i variablerne kan variere fra forekomst til forekomst.

Overvej Vækkeur klasse. Passerer snoozeInterval ind i udsætte () metoden er ikke et godt design. Forestil dig at skulle indtaste et udsættelsesinterval på dit vækkeur, hver gang du fumlede efter slumringsknappen. I stedet skal du bare give hele vækkeuret en snoozeInterval. Du udfylder dette med en instansvariabel i Vækkeur klasse, som vist nedenfor:

offentlig klasse AlarmClock {// Du erklærer snoozeInterval her. Dette gør det til en instansvariabel. // Du initialiserer det også her. lang m_snoozeInterval = 5000; // Udsæt tid i millisekunder = 5 sekunder. public void snooze () {// Du kan stadig komme til m_snoozeInterval i en AlarmClock-metode // fordi du er inden for klassens rækkevidde. System.out.println ("ZZZZZ for:" + m_snoozeInterval); }} 

Du kan få adgang til instansvariabler næsten hvor som helst inden for klassen, der erklærer dem. For at være teknisk omkring det erklærer du instansvariablen i klasses omfang, og du kan hente det næsten hvor som helst inden for dette omfang. Praktisk set kan du få adgang til variablen hvor som helst mellem den første krøllede parentes, der starter klassen og den afsluttende parentes. Da du også erklærer metoder inden for klassens omfang, kan de også få adgang til instansvariablerne.

Du kan også få adgang til forekomstvariabler uden for klassen, så længe der findes en forekomst, og du har en variabel, der refererer til forekomsten. For at hente en instansvariabel gennem en forekomst bruger du prikoperatør sammen med instansen. Det er måske ikke den ideelle måde at få adgang til variablen på, men fuldfør den indtil videre på denne måde til illustrative formål:

public class AlarmClockTest {public static void main (String [] args) {// Opret to ure. Hver har sin egen m_snoozeInterval AlarmClock aClock1 = ny AlarmClock (); AlarmClock aClock2 = ny AlarmClock (); // Skift aClock2 // Du vil snart se, at der er meget bedre måder at gøre dette på. aClock2.m_snoozeInterval = 10000; aClock1.snooze (); // Udsæt med aClock1s interval aClock2.snooze (); // Udsæt med aClock2s interval}} 

Prøv dette program, så ser du det aClock1 har stadig sit interval på 5.000, mens aClock2 har et interval på 10.000. Igen har hver instans sine egne instansdata.

Glem ikke, klassedefinitionen er kun et blueprint, så forekomstvariablerne eksisterer faktisk ikke, før du opretter forekomster fra blueprintet. Hver forekomst af en klasse har sin egen kopi af instansvariablerne, og planen definerer, hvad disse instansvariabler vil være.

JavaWorld

Indkapsling

Indkapsling er et af grundlaget for objektorienteret programmering. Når du bruger indkapsling, interagerer brugeren med typen gennem den eksponerede adfærd, ikke direkte med den interne implementering. Gennem indkapsling skjuler du detaljerne i en types implementering. I Java oversættes indkapsling grundlæggende til denne enkle retningslinje: "Få ikke direkte adgang til dit objekts data; brug dets metoder."

Det er en elementær idé, men det letter vores liv som programmører. Forestil dig for eksempel, at du ville instruere en Person modstand mod at rejse sig. Uden indkapsling kunne dine kommandoer gå sådan som: "Nå, jeg antager, at du bliver nødt til at stramme denne muskel her foran på benet, løsne denne muskel her på bagsiden af ​​benet. Hmmm - skal bøjes taljen også. Hvilke muskler udløser den bevægelse? Har du brug for at stramme disse, løsne dem. Whoops! Glemte det andet ben. Darn. Se det - væl ikke ... "Du får ideen. Med indkapsling skal du bare påberåbe dig stå op() metode. Temmelig let, ja?

Nogle fordele ved indkapsling:

  • Abstraktion af detaljer: Brugeren interagerer med en type på et højere niveau. Hvis du bruger stå op() metode, behøver du ikke længere kende alle de muskler, der kræves for at starte denne bevægelse.
  • Isolering fra ændringer:Ændringer i intern implementering påvirker ikke brugerne. Hvis en person forstuver sig i en ankel og afhænger af en stok i et stykke tid, påberåber brugerne stadig kunstå op()metode.
  • Korrekthed:Brugere kan ikke vilkårligt ændre indersiden af ​​et objekt. De kan kun gennemføre, hvad du tillader dem at gøre i de metoder, du skriver.

Her er et kort eksempel, hvor indkapsling klart hjælper med et programs nøjagtighed:

// Dårligt - bruger ikke indkapsling offentlig klasse Person {int m_age; } Public Class PersonTest {public static void main (String [] args) {Person p = new Person (); p.m_age = -5; // Hej - hvordan kan nogen være minus 5 år? }} // Bedre - bruger indkapsling offentlig klasse Person {int m_age; public void setAge (int age) {// Kontroller for at sikre, at alderen er større end 0. Jeg taler mere om // hvis udsagn på et andet tidspunkt. hvis (alder> 0) {m_age = alder; }}} offentlig klasse PersonTest {offentlig statisk ugyldig hoved (String [] args) {Person p = ny person (); p.setAge (-5); // Har ingen effekt nu. }} 

Selv det enkle program viser, hvordan du kan komme i problemer, hvis du direkte får adgang til de interne data i klasser. Jo større og mere komplekst programmet er, desto vigtigere bliver indkapslingen. Husk også, at mange programmer starter små og derefter vokser til ubestemt tid, så det er vigtigt, at du designer dem korrekt lige fra starten. For at anvende indkapsling på Vækkeur, kan du bare oprette metoder til at manipulere udsættelsesintervallet.

En note om metoder

Metoder kan returnere værdier, som den, der ringer op, bruger. For at returnere en værdi skal du erklære en ikke-ugyldig returtype og bruge en Vend tilbage udmelding. Det getSnoozeInterval () metoden vist i eksemplet nedenfor illustrerer dette.

Skriv programmet

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