1. Initialisering av variabler
Som du allerede vet, kan du deklarere flere variabler i klassen din, og ikke bare deklarere dem, men også umiddelbart initialisere dem med startverdiene.
Og de samme variablene kan også initialiseres i en konstruktør. Dette betyr at disse variablene i teorien kan tildeles verdier to ganger. Eksempel
Kode | Merk |
---|---|
|
Variabelen age tildeles en startverdi Startverdien overskrives Aldersvariabelen lagrer startverdien. |
|
Dette er tillatt: den første konstruktøren vil bli kalt |
|
Dette er tillatt: den andre konstruktøren vil bli kalt |
Dette er hva som skjer når Cat cat = new Cat("Whiskers", 2);
den utføres:
- Et
Cat
objekt er opprettet - Alle forekomstvariabler initialiseres med deres startverdier
- Konstruktøren kalles og dens kode kjøres.
Med andre ord, variablene får først sine startverdier, og først deretter blir koden til konstruktøren utført.
2. Rekkefølge for initialisering av variabler i en klasse
Variabler initialiseres ikke bare før konstruktøren kjører - de initialiseres i en veldefinert rekkefølge: rekkefølgen de er deklarert i klassen.
La oss se på en interessant kode:
Kode | Merk |
---|---|
|
Denne koden vil ikke kompilere, siden på tidspunktet variabelen a
opprettes, er det ingen b
og c
variabler ennå. Men du kan skrive koden din som følger - denne koden vil kompilere og vil fungere helt fint.
Kode | Merk |
---|---|
|
0 0+2 0+2+3 |
Men husk at koden din må være gjennomsiktig for andre utviklere. Det er bedre å ikke bruke teknikker som dette, siden det svekker lesbarheten til koden.
Her må vi huske at før variabler tildeles en verdi, har de en standardverdi . For int
typen er dette null.
Når JVM initialiserer a
variabelen, vil den ganske enkelt tildele standardverdien for int-typen: 0.
Når den når b
, vil a-variabelen allerede være kjent og ha en verdi, så JVM vil tildele den verdien 2.
Og når den når c
variabelen, vil variablene a
og b
allerede være initialisert, så JVM vil enkelt beregne startverdien for c
: 0+2+3.
Hvis du oppretter en variabel inne i en metode, kan du ikke bruke den med mindre du tidligere har tildelt en verdi til den. Men dette er ikke sant for variablene i en klasse! Hvis en startverdi ikke er tilordnet en variabel i en klasse, blir den tildelt en standardverdi.
3. Konstanter
Mens vi analyserer hvordan objekter skapes, er det verdt å berøre initialiseringen av konstanter, dvs. variabler med modifikatoren final
.
Hvis en variabel har final
modifikatoren, må den tildeles en startverdi. Du vet dette allerede, og det er ikke noe overraskende med det.
Men det du ikke vet er at du ikke trenger å tildele startverdien med en gang hvis du tilordner den i konstruktøren. Dette vil fungere helt fint for en endelig variabel. Det eneste kravet er at hvis du har flere konstruktører, må en endelig variabel tildeles en verdi i hver konstruktør.
Eksempel:
public class Cat
{
public final int maxAge = 25;
public final int maxWeight;
public Cat (int weight)
{
this.maxWeight = weight; // Assign an initial value to the constant
}
}
4. Kode i en konstruktør
Og noen flere viktige merknader om konstruktører. Senere, mens du fortsetter å lære Java, vil du komme over ting som arv, serialisering, unntak osv. De påvirker alle konstruktørenes arbeid i ulik grad. Det gir ingen mening å dykke dypt inn i disse temaene nå, men vi er forpliktet til i det minste å berøre dem.
For eksempel, her er en viktig bemerkning om konstruktører. I teorien kan du skrive kode av hvilken som helst kompleksitet i en konstruktør. Men ikke gjør dette. Eksempel:
|
Åpne en fil lesestrøm Les filen inn i en byte array Lagre byte array som en streng Vis filens innhold på skjermen |
I FilePrinter-klassekonstruktøren åpnet vi umiddelbart en bytestrøm på en fil og leste innholdet. Dette er kompleks oppførsel og kan føre til feil.
Hva om det ikke fantes en slik fil? Hva om det var problemer med å lese filen? Hva om den var for stor?
Kompleks logikk innebærer høy sannsynlighet for feil og det betyr at koden må håndtere unntak riktig.
Eksempel 1 — Serialisering
I et standard Java-program er det mange situasjoner der du ikke er den som lager objekter i klassen din. Anta for eksempel at du bestemmer deg for å sende et objekt over nettverket: i dette tilfellet vil Java-maskinen selv konvertere objektet ditt til et sett med byte, sende det og gjenskape objektet fra settet med byte.
Men anta at filen din ikke eksisterer på den andre datamaskinen. Det vil være en feil i konstruktøren, og ingen vil håndtere den. Og det er ganske i stand til å få programmet til å avslutte.
Eksempel 2 — Initialisering av felt i en klasse
Hvis klassekonstruktøren din kan kaste sjekkede unntak, dvs. er merket med nøkkelordet throws, må du fange opp de angitte unntakene i metoden som lager objektet ditt.
Men hva om det ikke finnes en slik metode? Eksempel:
Kode | Merk |
---|---|
|
Denne koden vil ikke kompilere. |
Klassekonstruktøren FilePrinter
kan kaste et sjekket unntak , som betyr at du ikke kan lage et FilePrinter
objekt uten å pakke det inn i en try-catch-blokk. Og en try-catch-blokk kan bare skrives i en metode
5. Basisklassekonstruktør
I tidligere leksjoner diskuterte vi arv litt. Dessverre er vår fulle diskusjon om arv og OOP reservert for nivået dedikert til OOP, og arv av konstruktører er allerede relevant for oss.
Hvis klassen din arver en annen klasse, vil et objekt fra den overordnede klassen bli innebygd i et objekt i klassen din. Dessuten har den overordnede klassen sine egne variabler og sine egne konstruktører.
Det betyr at det er veldig viktig for deg å vite og forstå hvordan variabler initialiseres og konstruktører kalles når klassen din har en overordnet klasse og du arver dens variabler og metoder.
Klasser
Hvordan vet vi i hvilken rekkefølge variabler initialiseres og konstruktører kalles? La oss starte med å skrive koden for to klasser. Den ene vil arve den andre:
Kode | Merk |
---|---|
|
Klassen ChildClass arver ParentClass klassen. |
Vi må bestemme rekkefølgen som variabler initialiseres og konstruktører kalles i. Logging vil hjelpe oss med dette.
Hogst
Logging er prosessen med å registrere handlinger utført av et program mens det kjører, ved å skrive dem til konsollen eller en fil.
Det er ganske enkelt å finne ut at konstruktøren har blitt kalt: i brødteksten til konstruktøren, skriv en melding til konsollen. Men hvordan kan du se om en variabel har blitt initialisert?
Faktisk er dette heller ikke veldig vanskelig: skriv en spesiell metode som vil returnere verdien som ble brukt til å initialisere variabelen, og logg initialiseringen. Slik kan koden se ut:
Endelig kode
|
Opprett et ChildClass objekt Denne metoden skriver den beståtte teksten til konsollen og returnerer den også. Erklær ParentClass klassen Vis tekst og initialiser også variablene med den. Skriv en melding om at konstruktøren har blitt kalt. Ignorer returverdien. Erklær ChildClass klassen Vis tekst og initialiser også variablene med den. Skriv en melding om at konstruktøren har blitt kalt. Ignorer returverdien. |
Hvis du kjører denne koden, vil teksten vises på skjermen som følger:
Konsollutgang av metodenMain.print() |
---|
|
Så du kan alltid personlig sørge for at variablene til en klasse initialiseres før konstruktøren kalles. En basisklasse initialiseres fullstendig før initialiseringen av den arvede klassen.
GO TO FULL VERSION