1. Initialisering af variabler
Som du allerede ved, kan du erklære flere variabler i din klasse, og ikke bare erklære dem, men også straks initialisere dem med deres begyndelsesværdier.
Og de samme variabler kan også initialiseres i en konstruktør. Det betyder, at disse variable i teorien kan tildeles værdier to gange. Eksempel
Kode | Bemærk |
---|---|
|
Variablen age tildeles en startværdi Startværdien overskrives Aldersvariablen gemmer dens startværdi. |
|
Dette er tilladt: den første konstruktør vil blive kaldt |
|
Dette er tilladt: den anden konstruktør vil blive kaldt |
Dette er, hvad der sker, når Cat cat = new Cat("Whiskers", 2);
det udføres:
- Et
Cat
objekt oprettes - Alle instansvariabler initialiseres med deres begyndelsesværdier
- Konstruktøren kaldes, og dens kode udføres.
Med andre ord får variablerne først deres startværdier, og først derefter udføres konstruktørens kode.
2. Rækkefølge for initialisering af variabler i en klasse
Variabler initialiseres ikke blot, før konstruktøren kører - de initialiseres i en veldefineret rækkefølge: den rækkefølge, de erklæres i i klassen.
Lad os se på noget interessant kode:
Kode | Bemærk |
---|---|
|
Denne kode vil ikke kompilere, da på det tidspunkt, hvor variablen a
oprettes, er der ingen b
og c
variabler endnu. Men du kan skrive din kode som følger - denne kode vil kompilere og vil køre fint.
Kode | Bemærk |
---|---|
|
0 0+2 0+2+3 |
Men husk, at din kode skal være gennemsigtig for andre udviklere. Det er bedre ikke at bruge teknikker som denne, da det forringer kodens læsbarhed.
Her skal vi huske, at før variabler tildeles en værdi, har de en standardværdi . For int
typen er dette nul.
Når JVM initialiserer a
variablen, vil den blot tildele standardværdien for int-typen: 0.
Når den når b
, vil a-variablen allerede være kendt og have en værdi, så JVM vil tildele den værdien 2.
Og når den når c
variablen, vil variablerne a
og b
allerede være initialiseret, så JVM vil nemt beregne startværdien for c
: 0+2+3.
Hvis du opretter en variabel inde i en metode, kan du ikke bruge den, medmindre du tidligere har tildelt en værdi til den. Men dette er ikke sandt for variablerne i en klasse! Hvis en startværdi ikke er tildelt en variabel i en klasse, tildeles den en standardværdi.
3. Konstanter
Mens vi analyserer, hvordan objekter skabes, er det værd at berøre initialiseringen af konstanter, dvs. variable med modifikatoren final
.
Hvis en variabel har final
modifikatoren, skal den tildeles en startværdi. Du ved det allerede, og der er ikke noget overraskende ved det.
Men hvad du ikke ved er, at du ikke behøver at tildele startværdien med det samme, hvis du tildeler den i konstruktøren. Dette vil fungere fint for en endelig variabel. Det eneste krav er, at hvis du har flere konstruktører, så skal en endelig variabel tildeles en værdi 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 et par vigtige bemærkninger om konstruktører. Senere, mens du fortsætter med at lære Java, vil du støde på ting som arv, serialisering, undtagelser osv. De påvirker alle konstruktørernes arbejde i forskellig grad. Det giver ingen mening at dykke dybt ned i disse emner nu, men vi er forpligtet til i det mindste at berøre dem.
For eksempel, her er en vigtig bemærkning om konstruktører. I teorien kan du skrive kode af enhver kompleksitet i en konstruktør. Men gør ikke dette. Eksempel:
|
Åbn en fillæsestrøm Læs filen ind i et byte-array Gem byte-arrayet som en streng Vis filens indhold på skærmen |
I FilePrinter-klassekonstruktøren åbnede vi straks en byte-stream på en fil og læste dens indhold. Dette er kompleks adfærd og kan resultere i fejl.
Hvad hvis der ikke var en sådan fil? Hvad hvis der var problemer med at læse filen? Hvad hvis den var for stor?
Kompleks logik indebærer en høj sandsynlighed for fejl, og det betyder, at koden skal håndtere undtagelser korrekt.
Eksempel 1 — Serialisering
I et standard Java-program er der masser af situationer, hvor du ikke er den, der opretter objekter i din klasse. Antag for eksempel, at du beslutter dig for at sende et objekt over netværket: i dette tilfælde vil Java-maskinen selv konvertere dit objekt til et sæt bytes, sende det og genskabe objektet fra sættet af bytes.
Men antag så, at din fil ikke findes på den anden computer. Der vil være en fejl i konstruktøren, og ingen vil håndtere den. Og det er ganske i stand til at få programmet til at afslutte.
Eksempel 2 — Initialisering af felter i en klasse
Hvis din klassekonstruktør kan kaste kontrollerede undtagelser, dvs. er markeret med throws nøgleordet, så skal du fange de angivne undtagelser i den metode, der opretter dit objekt.
Men hvad hvis der ikke er en sådan metode? Eksempel:
Kode | Bemærk |
---|---|
|
Denne kode vil ikke kompilere. |
Klassekonstruktøren FilePrinter
kan kaste en markeret undtagelse , hvilket betyder, at du ikke kan oprette et FilePrinter
objekt uden at pakke det ind i en try-catch-blok. Og en try-catch blok kan kun skrives i en metode
5. Basisklassekonstruktør
I tidligere lektioner diskuterede vi arv lidt. Desværre er vores fulde diskussion af arv og OOP forbeholdt niveauet dedikeret til OOP, og nedarvning af konstruktører er allerede relevant for os.
Hvis din klasse arver en anden klasse, vil et objekt fra den overordnede klasse blive indlejret i et objekt i din klasse. Hvad mere er, har den overordnede klasse sine egne variabler og sine egne konstruktører.
Det betyder, at det er meget vigtigt for dig at vide og forstå, hvordan variable initialiseres, og konstruktører kaldes, når din klasse har en overordnet klasse, og du arver dens variabler og metoder.
Klasser
Hvordan ved vi i hvilken rækkefølge variable initialiseres og konstruktører kaldes? Lad os starte med at skrive koden til to klasser. Den ene vil arve den anden:
Kode | Bemærk |
---|---|
|
Klassen ChildClass arver ParentClass klassen. |
Vi skal bestemme i hvilken rækkefølge variable initialiseres og konstruktører kaldes. Logning vil hjælpe os med dette.
Logning
Logning er processen med at registrere handlinger udført af et program, mens det kører, ved at skrive dem til konsollen eller en fil.
Det er ganske enkelt at fastslå, at konstruktøren er blevet kaldt: Skriv en besked til konsollen i konstruktørens krop. Men hvordan kan du se, om en variabel er blevet initialiseret?
Faktisk er dette heller ikke særlig svært: skriv en speciel metode, der returnerer den værdi, der blev brugt til at initialisere variablen, og log initialiseringen. Sådan kan koden se ud:
Endelig kode
|
Opret et ChildClass objekt Denne metode skriver den overførte tekst til konsollen og returnerer den også. Erklær ParentClass klassen Vis tekst og initialiser også variablerne med den. Skriv en besked om, at konstruktøren er blevet kaldt. Ignorer returværdien. Erklær ChildClass klassen Vis tekst og initialiser også variablerne med den. Skriv en besked om, at konstruktøren er blevet kaldt. Ignorer returværdien. |
Hvis du udfører denne kode, vil tekst blive vist på skærmen som følger:
Konsol output af metodenMain.print() |
---|
|
Så du kan altid personligt sikre dig, at variablerne i en klasse initialiseres, før konstruktøren kaldes. En basisklasse initialiseres fuldt ud før initialiseringen af den nedarvede klasse.
GO TO FULL VERSION