- Leren
- Informatica & ICT
- Programmeren
- Java programmeren: klassen, overerving, collecties en streams
- Java-klassen en objecten
Java-klassen en objecten
toString en rond af door een complete klasse te ontwerpen, bouwen en testen op basis van een korte beschrijving.BeginnerLes 5 van 11 in Cursus Java programmeren: klassen, overerving, collecties en streams
Wat je leert
- Leg uit hoe een klasse een nieuw gegevenstype met eigen gedrag definieert en maak en gebruik objecten van dat type in een programma.
- Leg uit wat een klasse en een object zijnBeschrijf een klasse als de definitie van een type, een object als één instantie daarvan en toestand en gedrag als wat objecten bevatten en doen.
- Maak objecten en roep hun methoden aanMaak objecten met
new, roep hun methoden aan met puntnotatie en voorspel hoe afzonderlijke objecten zich gedragen.
- Leg uit wat een klasse en een object zijn
- Declareer de instantievariabelen die de toestand van een object bevatten en schrijf constructoren die elk nieuw object geldige beginwaarden geven.
- Declareer instantievariabelenDeclareer velden met geschikte typen, ken hun standaardwaarden en onderscheid ze van lokale variabelen en parameters.
- Schrijf constructoren die objecten initialiserenSchrijf constructoren die elk veld instellen, gebruik
thisom velden van parameters te onderscheiden en vermijd fouten waardoor velden geen waarde krijgen. - Bied meerdere constructoren aan en keten dieOverlaad constructoren voor verschillende manieren om een object te maken en gebruik
this(...)zodat je de initialisatiecode één keer schrijft.
- Declareer instantievariabelen
- Schrijf instantiemethoden die de toestand van een object lezen en wijzigen, volg hun effect en bepaal wanneer iets bij een object of bij de klasse als geheel hoort.
- Schrijf instantiemethoden die de toestand gebruiken en wijzigenSchrijf methoden die informatie geven over de velden van een object of die wijzigen, roep andere methoden van hetzelfde object aan en volg de toestand van objecten stap voor stap.
- Onderscheid instantieleden van statische ledenGebruik
thisvoor het huidige object, bepaal wat statisch moet zijn en herstel fouten die ontstaan door statische code en instantiecode te mengen.
- Schrijf instantiemethoden die de toestand gebruiken en wijzigen
- Scherm velden af met toegangsmodifiers, geef gecontroleerde toegang via getters, setters en betekenisvolle methoden en houd elk object in een geldige toestand.
- Scherm gegevens af met toegangsmodifiersGebruik
private, pakkettoegang,protectedenpublicom te regelen welke code de leden van een klasse kan gebruiken, en leg uit waarom velden private worden gehouden. - Schrijf getters en settersSchrijf accessor- en mutatormethoden met de standaardnaamgeving en bepaal welke velden ze nodig hebben en wanneer een betekenisvolle methode beter is.
- Houd objecten geldig met controlesDefinieer de regels waaraan de toestand van een object moet voldoen, dwing die af in constructoren en methoden en voorkom dat je interne gegevens doorgeeft waarmee die controles kunnen worden omzeild.
- Scherm gegevens af met toegangsmodifiers
- Geef objecten een leesbare tekstvorm met
toStringen ontwerp, schrijf en test vervolgens een complete klasse op basis van een korte beschrijving.- Schrijf een toString-methodeSchrijf een
toString-methode die een leesbare beschrijving van een object teruggeeft en weet wanneer Java die automatisch aanroept. - Ontwerp, bouw en test een complete klasseZet een korte beschrijving om in een klasse met velden, constructoren, methoden en regels en test daarna elk gedrag vanuit een hoofdprogramma.
- Schrijf een toString-methode
Java-klassen en objecten: uitleg
1Klassen, objecten en methodeaanroepen
Een programma moet vaak meerdere samenhangende waarden bij elkaar houden, bijvoorbeeld de naam, diersoort en leeftijd van een huisdier. Een klasse geeft die groep een type en brengt de acties die de gegevens gebruiken op één plek samen. Je brengt klassedefinities in verband met de objecten die tijdens de uitvoering van een programma worden gemaakt en volgt vervolgens methodeaanroepen om te zien van welk object de gegevens veranderen. Het onderscheid tussen een klasse, een object en een variabele helpt je de code te lezen die je hierna schrijft.
1.1 Een type met toestand en gedrag
Een klasse definieert een type: de gegevens die de objecten onthouden en de bewerkingen die ze aanbieden. Een object, ook wel een instantie genoemd, is één waarde van dat type die wordt gemaakt terwijl een programma draait. Als je een klassedefinitie schrijft, maak je daarmee nog geen object.
Toestand en gedrag
De naam, diersoort en leeftijd van een huisdier vormen samen de toestand. Die huidige waarden staan in instantievariabelen, ook wel velden genoemd. Een bewerking zoals een verjaardag vieren is gedrag, geschreven als een methode. De verjaardagsmethode hoort bij de leeftijd die ze wijzigt, zodat de regel op één plek staat.
Zie een klasse als een bouwplan. Veel huizen kunnen volgens één plan worden gebouwd, maar elk huis heeft zijn eigen inhoud. Zo kunnen ook twee huisdieren dezelfde definitie volgen en verschillende leeftijden hebben. Je schrijft de veldnamen één keer; elk object krijgt zijn eigen waarden.
Lees een kleine klasse
public class Pet {
private String name;
private String species;
private int age;
public Pet(String name, String species, int age) {
this.name = name;
this.species = species;
this.age = age;
}
public void celebrateBirthday() {
this.age++;
}
}
Lees dit van buiten naar binnen. public class Pet introduceert het type en de buitenste accolades bevatten de definitie ervan. De eerste drie declaraties beschrijven de toestand. Het blok met de naam Pet is een constructor: die geeft een nieuw object zijn eerste waarden. celebrateBirthday is een methode: die verhoogt de leeftijd van het huidige object. De woorden private en public regelen de toegang; latere voorbeelden gebruiken ze om de toestand te beschermen.
De parameters van de constructor zijn waarden die worden meegegeven wanneer een object wordt gemaakt. In this.age = age; duidt de linkerkant het veld van het object aan en de rechterkant de meegegeven parameter. De constructor slaat die invoer op, zodat het object die kan onthouden nadat de constructie is voltooid.
Gebruik een klasse
Je hebt al bibliotheekklassen gebruikt. Scanner beschrijft objecten die invoer lezen, ArrayList beschrijft lijsten en een String-object biedt bewerkingen zoals length(). Een klasse die je zelf schrijft volgt hetzelfde basisidee: ze stelt een bruikbaar type beschikbaar aan de rest van je programma.
Zonder Pet zou een programma een naam, diersoort en leeftijd misschien afzonderlijk aan veel methoden doorgeven. Het moet elke groep correct bij elkaar houden. Een Pet-object bevat de samenhangende waarden als één geheel. Methoden op dat object weten welke leeftijd ze moeten gebruiken.
Orden en benoem de code
Bij gewone bronbestanden wordt een publieke klasse met de naam Pet opgeslagen in Pet.java, met dezelfde hoofdletters. Een afzonderlijke klasse Main kan de main-methode van het programma bevatten, huisdieren maken en hun methoden aanroepen. Pet heeft zelf geen main nodig. Klassen in hetzelfde naamloze pakket kunnen elkaar zonder imports gebruiken; in de eenvoudige voorbeelden staan die klassen in één map.
Gebruik zelfstandige naamwoorden in UpperCamelCase voor klassen, zoals LibraryBook. Gebruik lowerCamelCase voor velden en methoden: pageCount benoemt gegevens; giveBack() benoemt een actie. Dit zijn conventies die een lezer helpen elk onderdeel te herkennen, ook al staat de compiler veel andere namen toe.
Belangrijkste punten
- Een klasse definieert een type; een object is één instantie die wordt gemaakt terwijl het programma draait.
- Velden bevatten de toestand en methoden zorgen voor gedrag.
- Objecten van één klasse volgen dezelfde definitie en bevatten hun eigen waarden voor de instantievelden.
- Een publieke klasse in een gewoon bronbestand gebruikt de bijbehorende klassenaam als bestandsnaam.
1.2 Nieuwe objecten en de referenties ernaartoe
Een object maken en een variabele declareren zijn verschillende bewerkingen. Een variabele geeft je een naam waarmee je een object kunt bereiken; new maakt het object waarnaar de naam zal verwijzen.
Lees een instructie die een object maakt
Pet luna = new Pet("Luna", "cat", 3);
Pet is het type van de variabele en luna is de naam. new Pet(...) maakt een nieuw object en roept een passende constructor aan met drie argumenten. De constructor slaat de naam, diersoort en leeftijd op. De resulterende referentie wordt toegewezen aan luna.
Een referentie vertelt Java welk object moet worden gebruikt. Het is handig om een variabele te tekenen als een naam met een pijl naar een object. De variabele is geen tweede kopie van alle velden van het object.
Roep een methode aan op een bepaald object
De punt in luna.celebrateBirthday() verbindt een referentie met een methode die op het bijbehorende object wordt uitgevoerd. Een methode die iets teruggeeft, kan een waarde leveren aan een andere expressie:
luna.celebrateBirthday();
int years = luna.getAge();
System.out.println(years); // 4
Hier is getAge() een publieke methode die de leeftijd van het huisdier teruggeeft. De verjaardagsaanroep verandert de toestand; de getter leest die toestand. Pet.celebrateBirthday() werkt niet, omdat deze instantiemethode een bepaald huisdier nodig heeft. De klassenaam alleen geeft geen antwoord op de vraag wiens verjaardag het is.
Afzonderlijke objecten en gedeelde referenties
Pet max = new Pet("Max", "dog", 5);
luna.celebrateBirthday();
System.out.println(luna.getAge()); // 5
System.out.println(max.getAge()); // 5
Luna was al 4, dus door de volgende verjaardag wordt Luna 5. Max blijft 5. Gelijke leeftijden maken ze niet tot hetzelfde object: de twee new-expressies hebben afzonderlijke huisdieren gemaakt.
Bekijk nu een toewijzing zonder new:
Pet other = luna;
other.celebrateBirthday();
System.out.println(luna.getAge()); // 6
De toewijzing kopieert de referentie naar Luna. Beide namen verwijzen naar één huisdier, dus een wijziging via other is zichtbaar via luna. Roep new opnieuw aan om een tweede huisdier te maken.
Laat de argumenten passen bij de parameters van de constructor
Argumenten moeten passen bij het aantal, de volgorde en de typen van de parameters van een gedeclareerde constructor. Als de enige beschikbare constructor (String, String, int) verwacht, compileert new Pet() niet. Java raadt ontbrekende waarden niet. Als je de twee strings verwisselt, compileert de code echter wel: new Pet("cat", "Luna", 3) levert de juiste typen, maar de verkeerde betekenissen. Lees de parameternamen om de volgorde te controleren.
Deze twee onvoltooide pogingen mislukken om verschillende redenen:
Pet a; // declaration only
// System.out.println(a.getAge()); // a has no assigned value
// Pet b = Pet("Bo", "cat", 2); // missing new
Aan een lokale variabele moet een waarde zijn toegewezen voordat je die gebruikt. Zonder new zoekt Java naar een methode met de naam Pet, niet naar een expressie die een object maakt. Zodra een object bestaat, kan het weergeven ervan tekst zoals Pet@8bcc55f opleveren totdat je een leesbare toString()-methode schrijft; die uitvoer betekent niet dat de constructie is mislukt.
Belangrijkste punten
- Gebruik new met argumenten die passen bij een beschikbare constructor.
- Met puntnotatie roep je een instantiemethode aan op het object waarnaar een referentie verwijst.
- Een nieuwe new-expressie maakt een nieuw object; door een referentie toe te wijzen deel je een bestaand object.
- Argumenten van hetzelfde type kunnen zonder compilatiefout worden verwisseld, dus controleer hun betekenis.
- Een lokale declaratie alleen maakt geen object en geeft de variabele geen bruikbare waarde.
2Velden en de begintoestand van een object
Objecten hebben een plek nodig om hun gegevens te bewaren en een betrouwbare manier om hun eerste waarden te krijgen. Velden zorgen voor de opslag; constructoren initialiseren elk nieuw object. Je kiest veldtypen, onderscheidt blijvende toestand van tijdelijk lokaal werk en volgt de constructie van standaardwaarden tot een gebruiksklaar object. Daarna bied je verschillende bruikbare manieren aan om hetzelfde soort object te maken, terwijl gedeelde initialisatie en controles op één plek blijven.
2.1 Gegevens die een object onthoudt
Een object heeft een veld nodig voor elke waarde die het tussen methodeaanroepen moet onthouden. Kies die waarden voordat je methoden schrijft: ze vormen de blijvende toestand van het object.
Declareer velden met geschikte typen
Een veld staat binnen de accolades van de klasse, maar buiten alle constructoren en methoden. Een declaratie heeft een type en een naam nodig; er kunnen ook een toegangsmodifier en een initialisatiewaarde in staan.
private String title;
private int pageCount;
private boolean lentOut = false;
String is geschikt voor tekst, int voor een geheel aantal en boolean voor een ja-neetoestand. Velden kunnen ook klassetypen gebruiken, zoals ArrayList<String>. Deze voorbeelden gebruiken private; als je de modifier weglaat, krijg je pakkettoegang, geen private toegang.
Elk object krijgt een afzonderlijke kopie van elk instantieveld. Twee Rectangle-objecten hebben elk een width en een height, ook al staan de declaraties maar één keer in de klasse.
Standaardwaarden zijn niet altijd bruikbare beginwaarden
| Veldtype | Standaardwaarde |
|---|---|
int, long | 0 |
double | 0.0 |
boolean | false |
Klassetypen, waaronder String en ArrayList | null |
Een veld krijgt een standaardwaarde wanneer opslagruimte voor het object wordt gemaakt. Die waarde past mogelijk niet bij het doel van het object. Een lijstveld met de waarde null is geen lege lijst: je moet de lijst nog maken voordat je een element kunt toevoegen.
Lokale variabelen krijgen niet zo’n standaardwaarde. Binnen een methode compileert int total; gevolgd door System.out.println(total); niet, omdat aan total geen waarde is toegewezen. Houd de regel voor velden en de regel voor lokale variabelen uit elkaar.
Bepaal wat moet blijven bestaan
| Soort variabele | Waar gedeclareerd | Waarvoor bedoeld |
|---|---|---|
| Instantieveld | In de klasse, buiten methoden | Waarden die één object onthoudt |
| Parameter | In een constructor- of methodekop | Invoer voor die aanroep |
| Lokale variabele | Binnen een methode- of constructorblok | Tijdelijk werk voor die aanroep |
Een veld blijft bij het object. Een parameter is beschikbaar tijdens de bijbehorende aanroep en een lokale variabele is beschikbaar in het bijbehorende blok zolang die aanroep loopt. Als een teller zijn stand van de ene aanroep tot de volgende moet behouden, hoort die stand in een veld. Een tijdelijk subtotaal voor één berekening kan lokaal zijn.
Sla de invoer op; bereken afgeleide waarden
public class Rectangle {
private double width;
private double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
public double area() {
return this.width * this.height;
}
}
De afmetingen zijn in centimeters, dus area() geeft een oppervlakte in vierkante centimeters terug. Als je een apart veld voor de oppervlakte zou opslaan, ontstaat er nog een waarde die moet worden bijgewerkt wanneer een van de afmetingen verandert. Door de oppervlakte uit de afmetingen te berekenen blijft het antwoord consistent.
Gebruik een instantieveld met final voor een waarde die één keer wordt toegewezen, zoals private final String title;. Geef het veld een waarde in de declaratie of in elke constructor. final voorkomt hertoewijzing. static heeft een andere betekenis: het maakt één gedeeld klasseveld. Als je static toevoegt aan de naam van een huisdier, delen verschillende huisdieren één naamvariabele.
Belangrijkste punten
- Instantievelden worden buiten methoden gedeclareerd en onthouden de toestand van elk object.
- Velden krijgen standaardwaarden; aan lokale variabelen moet vóór gebruik een waarde zijn toegewezen.
- Kies velden voor blijvende gegevens en lokale variabelen voor tijdelijk werk.
- Bereken waarden die uit opgeslagen velden volgen om inconsistente kopieën te voorkomen.
- Aan een final-instantieveld wordt één keer een waarde toegewezen; een statisch veld wordt gedeeld door de klasse.
- Een lijstveld met null heeft nog een lijstobject nodig voordat je het kunt gebruiken.
2.2 Van argumenten naar geïnitialiseerde velden
Een constructor initialiseert een object wanneer new het maakt. De naam moet overeenkomen met de klassenaam en de constructor heeft geen retourtype. Zelfs void zou de declaratie tot een methode maken.
Zet invoer om in toestand
public Pet(String name, String species, int age) {
this.name = name;
this.species = species;
this.age = age;
}
Een constructor ontvangt invoer meestal als parameters en slaat die op in velden. Hier heeft elke parameter dezelfde naam als het bijbehorende veld. De naam age zonder toevoeging betekent de parameter; this.age betekent het veld van het object dat wordt gemaakt. De toewijzing leest de meegegeven waarde rechts en schrijft die naar het veld links.
Bij new Pet("Luna", "cat", 3) krijgen de velden van het nieuwe object eerst standaardwaarden: null, null en 0. De constructor ontvangt vervolgens de drie argumenten en vervangt die standaardwaarden. Wanneer de constructie is voltooid, levert new de referentie op die de aanroeper opslaat.
Twee fouten die compileren
public Pet(String name, String species, int age) {
name = name;
this.species = species;
this.age = age;
}
Beide keren verwijst name naar de parameter, dus de eerste regel wijst die parameter aan zichzelf toe. De naam van het object blijft null. De code is geldig en daarom is het belangrijk de waarden van het nieuwe object te controleren.
Een declaratie binnen de constructor veroorzaakt een verwant probleem:
String nick = initialNick;
Als er al een veld met de naam nick bestaat, maakt deze regel een lokale variabele met dezelfde naam. De lokale variabele verdwijnt wanneer de constructie eindigt. Schrijf this.nick = initialNick; om de invoer in het veld op te slaan; herhaal het type niet.
Weet wanneer er een constructor zonder parameters bestaat
Als een klasse geen constructoren declareert, levert Java een standaardconstructor zonder parameters. Bij een eenvoudige klasse behouden de velden hun gedeclareerde initialisatiewaarden of standaardwaarden. Zodra je zelf een constructor declareert, levert Java die standaardconstructor niet meer.
Een klasse met alleen Pet(String name, String species, int age) kan daarom niet worden gemaakt met new Pet(). Voeg alleen een expliciete constructor zonder parameters toe wanneer daarvoor een bruikbare begintoestand bestaat. Let ook op public void Pet(...): dat is een methode en levert dus helemaal niet de bedoelde constructor op.
Stel ook interne beginwaarden in
Niet elk veld hoeft uit een argument te komen. Een nieuw boek kan altijd beginnen met this.lentOut = false;. Een klasse die een lijst beheert, kan die zo initialiseren, met ArrayList geïmporteerd:
private ArrayList<String> tracks;
public Playlist() {
this.tracks = new ArrayList<>();
}
De lege lijst is klaar voor add. Als tracks op null blijft staan, mislukt een latere tracks.add(...) met NullPointerException.
Een veldinitialisator wordt vóór de constructorbody uitgevoerd. Als private int score = 10; wordt gevolgd door this.score = 5; in de constructor, is de score van het voltooide object 5. Test de waarden na de constructie, niet alleen de waarden die naast de velddeclaraties staan. Constructoren hebben ook dezelfde validatieregels nodig als latere wijzigingen, zodat de begintoestand geldig is.
Belangrijkste punten
- Een constructor heeft de klassenaam en geen retourtype.
- Gebruik this.field = parameter wanneer de namen overeenkomen.
- Noch een parameter aan zichzelf toewijzen, noch een nieuwe lokale variabele initialiseert het bedoelde veld.
- Java levert alleen een standaardconstructor wanneer de klasse geen constructoren declareert.
- Initialiseer de interne toestand, zoals lege lijsten, en pas validatie toe tijdens de constructie.
2.3 Meerdere manieren om één soort object te construeren
Een klasse kan meerdere bruikbare manieren aanbieden om een object te maken. Constructoren overladen betekent dat je constructoren met verschillende parameterlijsten declareert.
Onderscheid constructoren op basis van parameters
Java onderscheidt constructoren op basis van het aantal, de typen en de volgorde van hun parameters. Parameternamen maken geen onderscheid. Box(String label) en Box(String name) beschrijven dezelfde parameterlijst, dus ze kunnen niet allebei in één klasse worden gedeclareerd.
Een huisdier kan worden gemaakt met een leeftijd of als pasgeboren dier:
public Pet(String name, String species, int age) {
this.name = name;
this.species = species;
this.age = age;
}
public Pet(String name, String species) {
this(name, species, 0);
}
new Pet("Pip", "rabbit") selecteert de constructor met twee parameters. Die constructor geeft 0 als ontbrekende leeftijd mee en roept de constructor met drie parameters aan. Het nieuwe object eindigt met de toestand "Pip", "rabbit" en 0.
Keten de initialisatie van hetzelfde object
Binnen een constructor roept this(...) een andere constructor van dezelfde klasse aan. De kortere constructor kiest standaardwaarden; de uitgebreidere constructor voert de gedeelde initialisatie uit. Controles in die initialisatie gelden voor beide constructieroutes.
Vergelijk twee regels die op elkaar lijken:
| Regel binnen een constructor | Effect |
|---|---|
this(name, species, 0); | Initialiseert het huidige object via een andere constructor |
new Pet(name, species, 0); | Maakt een afzonderlijk huisdier |
De tweede regel vult de velden van het huidige object niet. Als het resultaat nooit wordt opgeslagen, wordt dat extra huisdier weggegooid. Het huidige huisdier kan nog steeds velden met null hebben.
Volg een keten voordat je latere code doorloopt
Een klok kan middernacht als standaardwaarde aanbieden:
public Clock() {
this(0, 0);
}
public Clock(int hours, int minutes) {
this.hours = hours;
this.minutes = minutes;
}
Voor new Clock() ga je naar de constructor zonder parameters, volg je this(0, 0) en wijs je beide velden toe in de constructor met twee parameters. Daarna keert de uitvoering terug naar de constructor zonder parameters. Dit maakt één klok, geen twee. Een aanroep van new Clock(9, 5) begint rechtstreeks in de uitgebreidere constructor.
Houd de keten geldig en duidelijk
Een constructor kan maximaal één aanroep van this(...) bevatten. De keten moet uiteindelijk een initialisatie bereiken die niet terug de keten in aanroept: twee constructoren die aan elkaar delegeren, veroorzaken tijdens het compileren een fout voor een recursieve constructoraanroep.
this(...) vooropzetten is een duidelijke stijl die in verschillende Java-versies werkt. In Java 24 en eerder zonder previewfuncties moet de aanroep vooropstaan. Java 25 staat voorafgaande instructies toe voor taken zoals het berekenen of controleren van argumenten. Die instructies mogen geen instantievelden van het huidige object lezen of instantiemethoden ervan aanroepen; toewijzingen aan velden die in de klasse zijn gedeclareerd zonder initialisatiewaarde in de declaratie zijn toegestaan.
Bied overladen constructoren aan omdat aanroepers verschillende bruikbare invoer hebben. Een klok die op middernacht begint is zinvol; een boek zonder titel misschien niet. Het bestaan van een volledige constructor maakt niet automatisch kortere overladen varianten.
Belangrijkste punten
- Overladen constructoren verschillen in parameterlijsten, niet in parameternamen.
- De aanroep this(...) delegeert aan een andere constructor op hetzelfde object.
- Houd gedeelde initialisatie en controles in één constructieroute.
- Een constructorketen mag niet teruglopen naar een constructor die al in die keten zit.
3Methoden die de toestand lezen en wijzigen
Een bruikbaar object kan vragen over zichzelf beantwoorden en acties uitvoeren die zijn toestand wijzigen. Instantiemethoden plaatsen die bewerkingen naast de velden die ze gebruiken. Je volgt wijzigingen instructie voor instructie, handelt de overgang van een klok af en geeft waarden terug die andere code kan gebruiken. Je bepaalt ook welke gegevens bij elk object horen en welke gegevens of bewerkingen bij de klasse horen, zodat afzonderlijke objecten gescheiden blijven.
3.1 Berekeningen, wijzigingen en toestandsverloop
Een instantiemethode wordt uitgevoerd voor één bepaald object. Declareer de methode zonder static en gebruik velden van dat object via namen zoals this.width. Bepaal wat de aanroeper nodig heeft: een toestandswijziging, een teruggegeven resultaat of beide.
Geef berekeningen terug; maak toestandswijzigingen expliciet
Voor een rechthoek waarvan de afmetingen in centimeters zijn opgeslagen:
public double area() {
return this.width * this.height;
}
public double perimeter() {
return 2 * (this.width + this.height);
}
public void scale(double factor) {
this.width = this.width * factor;
this.height = this.height * factor;
}
Een rechthoek met zijden van 3,0 en 4,0 heeft een oppervlakte van 12,0 vierkante centimeter en een omtrek van 14,0 centimeter. scale(2) verandert de zijden in 6,0 en 8,0. De volgende aanroepen geven oppervlakte 48,0 en omtrek 28,0 terug. Elke methode leest de huidige velden, dus er hoeft geen opgeslagen oppervlakte te worden bijgewerkt.
area() geeft een getal terug dat kan worden opgeslagen of in een berekening kan worden gebruikt. Als de methode het getal alleen zou weergeven en retourtype void zou hebben, zou de aanroeper niet double twice = r.area() * 2; kunnen schrijven. Laat de weergave aan de aanroeper over wanneer een methode als taak heeft een waarde te berekenen.
Werk samenhangende velden in volgorde bij
De methode advance() van een klok moet zowel de overgang van de minuten als die van de uren afhandelen:
public void advance() {
this.minutes++;
if (this.minutes == 60) {
this.minutes = 0;
this.hours++;
if (this.hours == 24) {
this.hours = 0;
}
}
}
Om 23.58 uur bereikt de eerste aanroep 23.59 uur en slaat beide blokken voor het terugzetten over. De volgende aanroep bereikt kortstondig minuut 60, zet die terug naar 0, verhoogt het uur naar 24 en zet dat terug naar 0. De uiteindelijke toestand is 00.00 uur. Nog één aanroep geeft 00.01 uur.
Volg objecten afzonderlijk
Schrijf na elke instructie een rij en maak een kolom voor de velden van elk object. Wijzig alleen het object dat de ontvanger van de aanroep aanduidt. Bij huisdieren van 2 en 7 jaar leiden twee verjaardagen van het eerste huisdier en setAge(1) op het tweede tot leeftijden van 4 en 1. Voer de body van een methode niet voor elke instantie uit alleen omdat ze een klasse delen.
Een lokale declaratie kan het veld afschermen dat je wilde bijwerken. public void reset() { int count = 0; } maakt alleen een tijdelijke variabele. this.count = 0; zet de blijvende tellerstand terug.
Hergebruik methoden en maak retourpaden compleet
Binnen een instantiemethode roepen area() en this.area() de oppervlaktemethode van hetzelfde object aan. Een beschrijvingsmethode kan die berekening hergebruiken in plaats van de expressie te kopiëren. Een methode kan ook de toestand wijzigen en teruggeven of dat is gelukt, zoals lend() doet wanneer die een boek als uitgeleend markeert en true meldt.
Een methode met een ander retourtype dan void kan niet zomaar het einde bereiken zonder een passende waarde terug te geven. Als get() alleen binnen if (count > 0) iets teruggeeft, wat gebeurt er dan wanneer de tellerstand 0 is? Voeg het ontbrekende retourpad toe of werp een exceptie op voor een waarde die de methode afwijst. Een pad dat een exceptie opwerpt, keert niet terug naar de aanroeper en heeft geen retourwaarde nodig.
Belangrijkste punten
- Instantiemethoden lezen of wijzigen de toestand van het object waarop ze worden aangeroepen.
- Geef berekende waarden terug zodat aanroepers ze in expressies kunnen gebruiken.
- Volg instructies in volgorde en houd de velden van elk object gescheiden.
- Methoden die een overgang afhandelen, moeten elk bijbehorend veld terugbrengen binnen het toegestane bereik.
- Hergebruik andere methoden van hetzelfde object door ze rechtstreeks of met this aan te roepen.
- Een methode die een waarde teruggeeft, heeft een waarde nodig op elk pad dat normaal terugkeert.
3.2 Leden per object en gedeelde klasseleden
Vraag van wie een waarde of bewerking is voordat je beslist of je static gebruikt. De leeftijd van een huisdier hoort bij één huisdier. Een telling van alle gemaakte huisdieren hoort bij de klasse als geheel.
Het huidige object is this
Binnen een constructor of instantiemethode verwijst this naar het object dat wordt geconstrueerd of de aanroep ontvangt. In this.age++ geeft het aan wiens leeftijd verandert. In this.name = name onderscheidt het het veld van een parameter met dezelfde naam. this(...) is de vorm waarmee je constructoren ketent.
Een statische methode heeft geen huidig object, dus this kan daar niet worden gebruikt. De methode kan nog steeds een object maken of een referentie ontvangen en die referentie gebruiken om instantiemethoden aan te roepen.
Gedeelde velden en velden per object
public class Counter {
private int count;
private static int created = 0;
public Counter() {
this.count = 0;
created++;
}
public void increment() {
this.count++;
}
public int getCount() {
return this.count;
}
public static int getCreated() {
return created;
}
}
Na twee aanroepen van new Counter() zijn er twee afzonderlijke count-velden, die beide aanvankelijk 0 zijn, en één created-veld met waarde 2. Als je de eerste teller verhoogt, verandert de stand daarvan in 1; de tweede blijft 0. Counter.getCreated() geeft nog steeds 2 terug omdat er geen nieuw object is geconstrueerd.
Werk vanuit main via een object
public static void main(String[] args) {
Counter c = new Counter();
c.increment();
System.out.println(c.getCount());
}
De klassieke main-methode is statisch. Een aanroep van increment() met alleen de naam zou daar geen doelobject hebben en niet compileren. De variabele c levert dat doelobject. Als je count statisch zou maken om de fout te laten verdwijnen, zou het ontwerp veranderen: elke teller zou dan één tellerstand delen.
| Soort methode | Rechtstreeks beschikbare toegang |
|---|---|
| Instantiemethode | De eigen instantieleden en de statische leden van de klasse |
| Statische methode | Statische leden; instantieleden via een objectreferentie |
Java 25 ondersteunt ook instantievormen van main, maar de klassieke statische kop blijft geldig. Deze voorbeelden gebruiken die consequent.
Kies methoden en constanten bewust
Een bewerking die de velden van een object nodig heeft, moet een instantiemethode zijn. Een bewerking die alleen van haar parameters afhangt, kan statisch zijn, zoals een hulpmethode die een totaal aantal minuten omzet naar uren. Statische aanroepen gebruiken normaal gesproken de klassenaam: Math.sqrt(16) of Counter.getCreated().
Een gedeelde vaste waarde wordt meestal als constante gedeclareerd:
public static final int MAX_CELSIUS = 30;
public maakt de constante beschikbaar voor aanroepers, static geeft de klasse één gedeeld veld en final voorkomt hertoewijzing. UPPER_SNAKE_CASE duidt volgens afspraak een constante aan. Dit is een gebruikelijke uitzondering op het private maken van velden. Gebruik static niet voor gewone namen, afmetingen of een andere toestand die tussen objecten moet verschillen.
Belangrijkste punten
- De referentie this duidt het huidige object aan binnen instantiecode.
- Statische leden horen bij de klasse; instantieleden horen bij afzonderlijke objecten.
- Een statische methode heeft een objectreferentie nodig om instantieleden te gebruiken.
- Herstel fouten met een statische context door het juiste object te gebruiken wanneer de toestand bij een object hoort.
- Een public static final-veld levert vaak een gedeelde constante.
4Gecontroleerde toegang en een geldige toestand
Een klasse moet bepalen welke waarden in haar toestand terecht kunnen komen. Met private velden en publieke methoden kan de klasse elke wijziging controleren en aanroepers bruikbare bewerkingen bieden. Je kiest toegangsniveaus, schrijft getters en setters waar die helpen en beschermt regels zoals een toegestaan temperatuurbereik. Je ziet ook waarom een private lijst toch via een getter kan uitlekken en hoe je voorkomt dat externe code de controles van de klasse omzeilt.
4.1 Private toestand en een publieke interface
Encapsulatie houdt de toestand van een object samen met de code die die toestand beheert. Velden zijn meestal private, terwijl aanroepers publieke bewerkingen gebruiken. Dit schermt opslagdetails af en geeft de klasse een plek om haar regels af te dwingen.
Kies een toegangsniveau
| Toegang | Wie het lid kan gebruiken |
|---|---|
private | Code in dezelfde klasse |
| Geen modifier | Code in hetzelfde pakket |
protected | Hetzelfde pakket, plus toegang voor subklassen volgens de Java-regels voor subklassen |
public | Code die toegang heeft tot het declarerende type |
Een pakket groepeert klassen. In de eenvoudige voorbeelden staan gewone klassen bij elkaar zonder een package-declaratie, in één naamloos pakket. Pakkettoegang ontstaat door de modifier weg te laten; er is geen toegangssleutelwoord package dat je aan een veld kunt toevoegen.
Begin met de meest beperkte bruikbare toegang. Maak velden private, constructoren en bewerkingen die andere klassen nodig hebben public en interne hulpmethoden private. Publieke constanten zijn een gebruikelijke uitzondering voor velden.
Laat de klasse wijzigingen beheren
Als Pet private int age; declareert, kan een afzonderlijke klasse Main niet luna.age = -5; toewijzen. De compiler wijst de toegang af. Een aanroep zoals luna.setAge(-5) kan wel worden toegestaan, omdat de publieke methode bij Pet hoort en kan beslissen of het argument wordt opgeslagen.
Met een public veld zou elke aanroeper die methode kunnen omzeilen. Zodra alle wijzigingen via de code van de klasse lopen, kunnen de controles op één plek staan. Private toegang alleen valideert een leeftijd niet; de methoden moeten de controles ook uitvoeren.
Houd de publieke interface stabiel
Stel dat een klok aanvankelijk afzonderlijke velden hours en minutes opslaat. Aanroepers gebruiken getHours() en getMinutes(). Later vervang je de velden door één waarde minutesSinceMidnight:
public int getHours() {
return this.minutesSinceMidnight / 60;
}
public int getMinutes() {
return this.minutesSinceMidnight % 60;
}
Met 615 opgeslagen minuten geeft de deling 10 terug en de restbewerking 15. De klok geeft via dezelfde methoden 10.15 uur aan. Aanroepers hoeven niet te worden herschreven omdat ze afhankelijk waren van de publieke bewerkingen, niet van de manier waarop de toestand werd opgeslagen. Deze vrijheid om de interne werking te wijzigen heet informatieafscherming.
Toegang hoort bij klassen, niet bij afzonderlijke objecten
Code binnen Pet kan een privéveld van een ander Pet-object lezen. De toegang volgt uit het feit dat de code binnen de klasse staat. Een andere klasse op het hoogste niveau krijgt geen toegang doordat die een referentie naar een huisdier heeft of in dezelfde map staat.
Voor gewone klassedeclaraties op het hoogste niveau zijn de toegangskeuzes public of geen modifier. Een private class Pet op het hoogste niveau is niet toegestaan. Een publieke klasse op het hoogste niveau hoort in het bijbehorende bronbestand en één gewoon bronbestand bevat maximaal één publieke klasse op het hoogste niveau.
Private velden vormen een grens in het programmaontwerp. Ze voorkomen dat andere gewone code rechtstreeks afhankelijk wordt van interne velden, maar zijn geen manier om een waarde geheim te houden voor iemand die het programma kan bekijken. Gebruik ze om de interface van je klasse te beheren en de toestand ervan te beschermen.
Belangrijkste punten
- Private velden en publieke bewerkingen houden de controle over de toestand binnen de klasse.
- Als je een toegangsmodifier weglaat, krijg je pakkettoegang.
- Dankzij publieke methoden kan de interne opslag veranderen zonder de aanroepers te wijzigen.
- Private toegang wordt per klasse gecontroleerd, dus code binnen de klasse kan de velden van een andere instantie benaderen.
- Gewone klassen op het hoogste niveau gebruiken public of pakkettoegang.
4.2 Toegangsmethoden die bij de klasse passen
Een klasse kan aanroepers geselecteerde delen van haar toestand laten lezen of wijzigen via methoden. Bepaal welke bewerkingen de klasse moet aanbieden voordat je voor elk veld toegangsmethoden maakt.
Geef waarden terug met getters
Een getter, ook wel een accessor genoemd, geeft informatie terug zonder het object te wijzigen. Een gebruikelijke getter leest een veld:
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
Het retourtype past bij de informatie die wordt geleverd. Een getter die iets weergeeft en void teruggeeft, kan geen waarde leveren aan een expressie zoals pet.getAge() + 1. De aanroeper moet de waarde ontvangen en beslissen hoe die wordt gebruikt.
Wijzig geselecteerde waarden met setters
Een setter, ook wel een mutator genoemd, neemt een nieuwe waarde aan en werkt de toestand bij:
public void setName(String name) {
this.name = name;
}
this.name is het veld. name is de parameter. Als je name = name; schrijft, compileert de code, maar verandert er geen veld. Er is hier geen retourwaarde omdat deze setter als taak heeft een wijziging uit te voeren.
Voor een huisdier van 3 jaar:
luna.setName("Lulu");
System.out.println(luna.getName() + " is " + luna.getAge());
// Lulu is 3
De aanroeper benadert een veld nooit rechtstreeks. De setter verandert de naam en de getters geven de huidige waarden terug zodat de aanroeper die kan combineren.
Volg de naamgeving die andere Java-code verwacht
| Veld | Getter | Setter, indien nodig |
|---|---|---|
pageCount | getPageCount() | setPageCount(int pageCount) |
name | getName() | setName(String name) |
lentOut | isLentOut() | setLentOut(boolean lentOut) |
Schrijf de eerste letter van de veldnaam als hoofdletter na get, set of het gebruikelijke booleaanse voorvoegsel is. Een naam zoals getname() kan compileren, maar volgt niet de conventie die hulpmiddelen en andere programmeurs verwachten.
Bied alleen bruikbare bewerkingen aan
De titel van een boek kan een getter hebben en geen setter, omdat aanroepers de titel wel mogen lezen maar niet vervangen. Een private final-veld kan afdwingen dat er één keer een waarde aan wordt toegewezen. Een interne teller heeft mogelijk geen getter en geen setter nodig als alleen de klasse die gebruikt.
Een setter zonder controle kan dezelfde schadelijke waarde accepteren als een public veld. Voeg controles toe waar een wijziging beperkingen heeft. Overweeg ook een actiemethode: celebrateBirthday() drukt uit dat de leeftijd met één wordt verhoogd en lend() drukt een uitleenpoging uit. lend() kan de huidige toestand bekijken en een tweede uitlening weigeren. Een setter kan die controle ook uitvoeren; de actienaam maakt de bewerking duidelijker voor de aanroeper.
Een getter kan een antwoord berekenen. getArea() kan het product van breedte en hoogte teruggeven zonder een veld area.
Belangrijkste punten
- Een getter geeft informatie terug; een setter wijzigt een geselecteerde waarde.
- Volg het naamgevingspatroon getName, setName en het gebruikelijke booleaanse isName.
- Geef velden alleen de toegangsmethoden die aanroepers nodig hebben.
- Actiemethoden zoals lend drukken toegestaan gedrag duidelijk uit en kunnen overgangen controleren.
4.3 Regels die bij elke wijziging blijven gelden
Een invariant is een regel voor de toestand van een object die geldt na de constructie en na elke publieke bewerking. Een thermostaat kan doeltemperaturen van 5 °C tot en met 30 °C toestaan. Elke manier om de doeltemperatuur in te stellen moet dat bereik respecteren.
Kies wat ongeldige invoer betekent
Drie bruikbare reacties zijn de oude waarde behouden, de waarde tot een grens begrenzen of een exceptie opwerpen. Ze hebben verschillende effecten, dus kies voor elke bewerking een duidelijke reactie.
| Reactie | Resultaat van een ongeldige aanroep |
|---|---|
| Negeren | De oude veldwaarde blijft ongewijzigd |
| Begrenzen | De dichtstbijzijnde toegestane grens wordt opgeslagen |
| Exceptie opwerpen | De aanroep stopt met een fout zoals IllegalArgumentException |
Voor een niet-negatieve leeftijd van een huisdier kan een setter die ongeldige waarden negeert alleen binnen if (age >= 0) een waarde toewijzen. Als de opgeslagen leeftijd 4 is, laat setAge(-2) die op 4 staan. De leeftijd wordt niet 0.
Plaats bereikcontroles binnen de klasse
public static final int MIN_CELSIUS = 5;
public static final int MAX_CELSIUS = 30;
private int target;
public void setTarget(int celsius) {
if (celsius < MIN_CELSIUS) {
this.target = MIN_CELSIUS;
} else if (celsius > MAX_CELSIUS) {
this.target = MAX_CELSIUS;
} else {
this.target = celsius;
}
}
public void raise() {
setTarget(this.target + 1);
}
Beginnend bij 20 °C slaat setTarget(35) 30 op. setTarget(-3) slaat 5 op. Na setTarget(29) slaat een aanroep van raise() 30 op; een volgende aanroep slaat nog steeds 30 op. Door de setter te hergebruiken kan raise() de bovengrens niet overschrijden.
Controles in alleen Main kunnen de thermostaat niet beschermen. Een andere aanroeper zou ze kunnen vergeten. De klasse moet de invoer controleren op de plek waar ze de opslag beheert.
Valideer ook de begintoestand
public Thermostat(int target) {
setTarget(target);
}
Met deze begrenzende constructor eindigt new Thermostat(50) op 30 °C. Door rechtstreeks this.target = target; toe te wijzen zou de ongeldige begintoestand 50 worden toegestaan. Een gedeelde private controlemethode is een andere manier om validatie in constructoren en latere methoden te hergebruiken.
Een exceptie opwerpen is nuttig wanneer een ongeldig argument op een programmeerfout wijst. Een constructor kan bijvoorbeeld een negatief aantal afwijzen met throw new IllegalArgumentException("count must not be negative");. Het object wordt niet succesvol geconstrueerd, dus de aanroeper krijgt geen ongeldig voltooid object. Invoer negeren is eenvoudiger maar gebeurt stilzwijgend; de aanroeper heeft mogelijk een andere manier nodig om te merken dat er niets is veranderd.
Houd veranderlijke interne gegevens binnen de klasse
Een private lijst kan nog steeds uitlekken als een getter de oorspronkelijke lijst teruggeeft. Een aanroeper zou dan elementen kunnen toevoegen of verwijderen zonder de methoden van de klasse te gebruiken en zo een regel voor de maximale grootte omzeilen.
Voor een ArrayList<String>-veld met de naam tracks geeft return new ArrayList<>(this.tracks); een afzonderlijke lijst met dezelfde strings terug. Als je die teruggegeven lijst wijzigt, verandert de interne lijst niet. Bewerkingen zoals addTrack(String title) kunnen lijstwijzigingen binnen de klasse houden en de regels controleren voordat ze wijzigingen accepteren.
Belangrijkste punten
- Een invariant geldt na de constructie en na elke publieke bewerking.
- Negeren, begrenzen tot een interval en een exceptie opwerpen zijn verschillende reacties op ongeldige invoer.
- Elke constructor en elke methode die de toestand wijzigt, moet dezelfde regels handhaven.
- Hergebruik validatie zodat verschillende wijzigingsroutes die niet kunnen omzeilen.
- Als je een interne veranderlijke lijst teruggeeft, kunnen aanroepers de controles van de klasse omzeilen.
- Een kopie van een interne stringlijst beschermt de oorspronkelijke lijst tegen wijzigingen van buitenaf.
5Leesbare objecten en complete klassen
Leesbare objectbeschrijvingen maken het gemakkelijker om een klasse te gebruiken en te controleren. Een toString-methode levert die tekst overal waar een object wordt weergegeven of met een string wordt samengevoegd. Je schrijft de methode met de juiste kop en brengt daarna velden, constructoren, methoden en validatie samen in een complete klasse. Op basis van een korte beschrijving zet je vereisten om in code en test je gewone aanroepen, herhaalde acties en grensgevallen.
5.1 Een objectbeschrijving als tekst teruggeven
Een bruikbaar object moet gemakkelijk als tekst te bekijken zijn. De ingebouwde Java-methode toString() geeft een klassenaam, een @-teken en een hexadecimale hashcode terug, zoals Pet@8bcc55f. Een benoemd pakket wordt onderdeel van de klassenaam. De hashtekst varieert en zegt meestal weinig over de toestand van het object.
Geef een leesbare beschrijving terug
@Override
public String toString() {
return this.name + " (" + this.species + ", "
+ this.age + " years)";
}
Voor Luna, een kat van 3 jaar, is de teruggegeven string "Luna (cat, 3 years)". De methode leest velden en bouwt een string op. Ze verandert het huisdier niet en stuurt geen uitvoer naar het scherm.
@Override vraagt de compiler te controleren of de declaratie echt een bestaande methode vervangt. Dat ontdekt fouten zoals tostring schrijven met een kleine s. De annotatie maakt het resultaat niet voor je op; de retourwaarde wordt bepaald door de return-expressie.
Herken automatische aanroepen
System.out.println(luna);
String label = "Pet: " + luna;
String details = luna.toString();
De eerste regel geeft de leesbare beschrijving van het huisdier weer. De tweede bouwt "Pet: Luna (cat, 3 years)" op. De derde vraagt expliciet dezelfde beschrijving op en slaat die op zonder die weer te geven. Wanneer een ArrayList met huisdieren wordt weergegeven, gebruikt de weergave van de lijst de toString() van elk huisdier tussen de vierkante haken van de lijst.
Door de automatische omzetting is het belangrijk tekst terug te geven. De aanroeper kan het resultaat weergeven, opslaan of samenvoegen. Een methode die alleen iets weergeeft, kan niet de string leveren die al die aanroepers nodig hebben.
Laat de methodekop overeenkomen
| Declaratie | Wat gebeurt er |
|---|---|
public String toString() | Levert de objectbeschrijving |
public String tostring() | Declareert een andere methode; @Override ontdekt dit |
public String toString(int width) | Declareert een overladen methodevariant; automatische weergave roept die niet aan |
public void toString() | Mislukt: is in strijd met de bestaande methode die een String teruggeeft |
Gebruik de exacte kop zonder parameters en voeg de annotatie toe. Een overladen methodevariant met parameters kan een geldige afzonderlijke methode zijn, maar bij het weergeven van een object worden die parameters niet meegegeven.
Maak waarden op zonder ze te veranderen
Een klok heeft uren en minuten met twee cijfers nodig. Binnen de methode toString():
return String.format(java.util.Locale.US,
"%02d:%02d", this.hours, this.minutes);
Voor uren 9 en minuten 5 is de string "09:05". Elke %02d maakt een geheel getal op met minstens twee posities en gebruikt zo nodig een voorloopnul. String.format(java.util.Locale.US, "%.2f", 7.5) geeft "7.50" terug. Door de taal- en regio-instelling mee te geven is de uitvoer met een decimale punt onafhankelijk van de standaardinstelling voor opmaak van de computer.
Houd de beschrijving kort genoeg om te lezen tijdens het opsporen van fouten. Ze kan een niet-ingestelde toestand zichtbaar maken: als je een naamveld met null samenvoegt met een string, ontstaat de tekst "null", die je terugleidt naar de initialisatie. De beschrijving moet de huidige toestand melden, dus als je het object twee keer weergeeft, mag dat een klok niet vooruitzetten of een verjaardag vieren.
Belangrijkste punten
- Schrijf public String toString() zonder parameters en geef leesbare tekst terug.
- Met de annotatie @Override kan de compiler controleren of de methode een bestaande methode vervangt.
- Bij het weergeven van een object en het samenvoegen met een string wordt toString automatisch gebruikt.
- Laat toString de toestand niet wijzigen en laat de aanroeper bepalen waar de tekst terechtkomt.
- String.format kan waarden aanvullen en een expliciete taal- en regio-instelling gebruiken voor voorspelbare uitvoer.
5.2 Van een vereiste naar een geteste klasse
Begin met wat één object moet onthouden, wat aanroepers het kunnen laten doen en welke toestanden moeten zijn toegestaan. Zet daarna elk onderdeel om in velden, constructoren en methoden.
Haal het ontwerp uit een beschrijving
“Een bibliotheekboek heeft een titel, een auteur en een aantal pagina’s. Het kan worden uitgeleend en teruggebracht. Het kan niet opnieuw worden uitgeleend zolang het al is uitgeleend.”
Gebruik LibraryBook als klassenaam. Sla de drie beschrijvende waarden en een booleaanse uitleenstatus op. De titel, auteur en het aantal pagina’s blijven vast, dus maak ze final. De uitleenstatus verandert door betekenisvolle acties. Een setter voor elk veld is niet nodig.
Bouw de complete klasse
public class LibraryBook {
private final String title;
private final String author;
private final int pages;
private boolean lentOut;
public LibraryBook(String title, String author, int pages) {
this.title = title;
this.author = author;
this.pages = pages;
this.lentOut = false;
}
public boolean isLentOut() {
return this.lentOut;
}
public boolean lend() {
if (this.lentOut) {
return false;
}
this.lentOut = true;
return true;
}
public void giveBack() {
this.lentOut = false;
}
@Override
public String toString() {
String status = this.lentOut ? "lent out" : "available";
return this.title + " by " + this.author + ", "
+ this.pages + " pages, " + status;
}
}
De constructor maakt het boek beschikbaar. lend() controleert de bestaande toestand voordat die verandert; door bij een tweede uitlening false terug te geven blijft de regel gehandhaafd. giveBack() maakt het boek beschikbaar. De getter meldt de status en toString() beschrijft het hele boek zonder het te veranderen.
Schrijf verwachtingen op voordat je aanroepen uitvoert
In de klassieke main-methode van een afzonderlijke klasse Main:
LibraryBook b = new LibraryBook("Night Train", "A. Rivera", 320);
System.out.println(b); // Night Train by A. Rivera, 320 pages, available
System.out.println(b.lend()); // true
System.out.println(b.lend()); // false
b.giveBack();
System.out.println(b.lend()); // true
De tweede uitleenpoging is essentieel: een methode die altijd de vlag instelt en true teruggeeft, zou bij de eerste aanroep slagen maar niet bij deze controle. Test de retourwaarden en controleer ook de toestand met isLentOut(). Probeer ook een tweede boek om te controleren of het uitlenen van het ene boek het andere beschikbaar laat.
Test waar het gedrag verandert
Zorg dat je tests elke constructor en publieke methode dekken. Probeer bij bereikcontroles beide grenswaarden en waarden net daarbuiten. Controleer bij een klok de overgang van de minuten en de overgang naar middernacht. Controleer bij een setter die ongeldige invoer afwijst of negeert of die invoer het beloofde effect op de oude toestand heeft. Schrijf eerst het verwachte resultaat op, zodat onverwachte uitvoer niet ongemerkt je nieuwe verwachting wordt.
Bouw in kleine stappen: eerst velden en constructor, dan een leesbare beschrijving en daarna steeds één bewerking met de bijbehorende controles. Sla gewone publieke klassen op in bestanden met overeenkomstige namen, compileer ze samen en voer de klasse uit die main bevat. Door modelbewerkingen gescheiden te houden van schermuitvoer kan dezelfde klasse verschillende programma’s dienen.
Belangrijkste punten
- Zet gegevens die moeten worden onthouden om in private velden en toegestane acties in methoden.
- Schrijf de toestandsregels op voordat je constructoren en wijzigingen implementeert.
- Gebruik final voor vaste waarden per object en vermijd onnodige setters.
- Test retourwaarden en de resulterende toestand, ook bij herhaalde aanroepen en afzonderlijke objecten.
- Controleer grenswaarden en ongeldige invoer naast gewone waarden.
- Bouw en test steeds één bruikbaar onderdeel.
- Houd het gedrag van het model gescheiden van het hoofdprogramma dat resultaten weergeeft.
Java-klassen en objecten: voorbeelden
1Van één klasse naar twee huisdieren
10 stappen
- 1IntroductieEen type voor de dingen in je programma
Een programma over huisdieren moet een naam, diersoort en leeftijd samen onthouden. Een klasse geeft die groep een type en biedt methoden die de gegevens gebruiken. Elk object is één huisdier dat vanuit die definitie is gemaakt.
Volg het verschil tussen de definitie en de huisdieren die eruit voortkomen. Volg daarna twee huisdierobjecten en bekijk waarom een extra variabele niet altijd een extra object betekent.
- 2AnalogieEen plan en de instanties ervan
Zie een klasse als een bouwplan en de objecten als huizen die daarmee worden gebouwd. Het plan beschrijft wat elk huis bevat, maar is zelf geen huis.
Eén definitie van
Petkan veel huisdieren beschrijven. Elk heeft velden voor dezelfde soorten gegevens, maar het ene kan een kat van drie jaar zijn en het andere een hond van vijf jaar. Door de velden te definiëren maak je het plan; door objecten te maken ontstaan echte instanties. - 3VoorbeeldBepaal toestand en gedrag
De velden
name,speciesenagevan een huisdier slaan de toestand op. Voor Luna zijn de waarden"Luna","cat"en3.De methode
celebrateBirthday()zorgt voor gedrag. De body kanthis.age++;uitvoeren en zo de leeftijd van het ontvangende huisdier veranderen. De methode maakt deel uit van de klassedefinitie; de waarde die ze verandert hoort bij een bepaald huisdier. - 4UitdagingMaakt een definitie een huisdier?
Een programmeur schrijft een klasse
Petmet drie velden en een verjaardagsmethode. Er is geen expressie uitgevoerd die een object maakt. Hoeveel huisdierobjecten heeft die definitie gemaakt?---reveal---
Geen. De klasse definieert een type en de beschikbare toestand en het beschikbare gedrag. Objecten ontstaan wanneer het programma ze maakt, bijvoorbeeld met
new Pet(...). Drie velddeclaraties beschrijven drie gegevens per huisdier, niet drie huisdieren. - 5VoorbeeldMaak het eerste object
Lees
Pet luna = new Pet("Luna", "cat", 3);in delen.Pet lunadeclareert een variabele.new Pet(...)maakt een huisdier en voert de constructor uit met de drie meegegeven argumenten.De constructor slaat de beginwaarden op. De referentie die
newoplevert, wordt toegewezen aanluna, zodat latere code dit object kan bereiken. AlleenPet luna;declareren zou geen object opleveren waarop je een methode kunt aanroepen. - 6UitlegRoep een methode aan op haar ontvanger
In
luna.celebrateBirthday()duidt de expressie vóór de punt de ontvanger aan. De verjaardagsmethode wordt uitgevoerd voor Luna en verhoogt Luna’s leeftijd van 3 naar 4.int age = luna.getAge();haalt vervolgens de huidige leeftijd op voor gebruik elders.Pet.celebrateBirthday()kan geen huisdier kiezen: dit is een instantiemethode en een klassenaam levert geen bepaald object. - 7VoorbeeldMaak een tweede huisdier
Voer nu
Pet max = new Pet("Max", "dog", 5);uit. Een tweedenew-expressie maakt een tweede object met eigen velden.Na nog een keer
luna.celebrateBirthday()is Luna 5 en Max nog steeds 5. Hun gelijke leeftijden maken ze niet tot hetzelfde object. Een latere verjaardag van Luna verandert alleen Luna’s leeftijd, omdat Max’ leeftijd in de velden van een ander object staat. - 8KernpuntMet een toewijzing kun je één object delen
Pet other = luna;kopieert Luna’s referentie. De toewijzing roept geen constructor aan en kopieert Luna’s velden niet naar een ander huisdier.De namen
otherenlunaverwijzen nu naar hetzelfde object. Als jeother.celebrateBirthday()aanroept, verandert de leeftijd van dat huisdier van 5 naar 6 en zietluna.getAge()ook 6. Tel het maken van objecten afzonderlijk van het declareren van variabelen. - 9UitdagingVolg een gedeelde referentie en een afzonderlijk huisdier
Twee afzonderlijke huisdieren beginnen met leeftijd 1 voor
aen 8 voorb. De code voertPet c = a; c.celebrateBirthday(); b.celebrateBirthday();uit. Welke leeftijden meldenaenb?---reveal---
Ze melden 2 en 9.
cdeelt het object vana, dus de aanroep verhoogt de leeftijd van dat huisdier. De aanroep viabverhoogt de leeftijd van het afzonderlijke huisdier. De klasse biedt beide hetzelfde verjaardaggedrag, maar elke aanroep heeft een eigen ontvanger. - 10SamenvattingLees het maken van objecten en aanroepen aandachtig
Houd drie rollen uit elkaar: de klasse definieert het type, elk object bevat zijn eigen instantietoestand en een referentievariabele verwijst naar een object.
Markeer bij het lezen van code elke
new, vergelijk de argumenten met de constructor en bepaal de ontvanger voordat je een methodeaanroep volgt. Een gewone referentietoewijzing voegt een route naar een bestaand object toe. Een tweedenewmaakt een afzonderlijk object met een eigen toestand.
2Bouw de begintoestand correct op
14 stappen
Sla deze les op om elke Walkthrough stap voor stap te volgen.
- 1IntroductieGeef elk nieuw object bruikbare gegevens
- 2UitlegKies blijvende toestand
- 3UitlegOnderscheid standaardwaarden van bruikbare waarden
- 4UitdagingKies een veld of een lokale variabele
- 5UitlegLees de constructorkop
- 6VoorbeeldZet parameters over naar velden
- 7TipEen geldige toewijzing die niets opslaat
- 8UitdagingZoek het ongewijzigde veld
- 9VerbandMaak ook interne objecten
- 10VoorbeeldBied een bruikbare standaardroute aan
- 11UitlegVolg één object door de keten
- 12UitdagingAnalyseer een misleidende new-expressie
- 13UitdagingCombineer een vast veld met een overladen constructor
- 14SamenvattingControleer elke route naar een voltooid object
3Volg veranderende en gedeelde toestand
13 stappen
Sla deze les op om elke Walkthrough stap voor stap te volgen.
- 1IntroductieVolg wat elke aanroep verandert
- 2UitlegGeef een waarde terug aan de aanroeper
- 3VoorbeeldSchaal de opgeslagen afmetingen
- 4UitdagingControleer het teruggegeven resultaat na een wijziging
- 5VoorbeeldGa voorbij middernacht
- 6TipHerstel een reset die de toestand niet wijzigt
- 7KernpuntZorg voor elke normale terugkeer
- 8UitlegOnderscheid twee tellerstanden van één gedeelde teller
- 9VoorbeeldGebruik een object in statische code
- 10VerbandHerken een constante
- 11UitdagingVolg de twee soorten toestand
- 12UitdagingZoek waarom afzonderlijke objecten samen veranderen
- 13SamenvattingKoppel elke bewerking aan de eigenaar
4Bescherm elke route naar de toestand
14 stappen
Sla deze les op om elke Walkthrough stap voor stap te volgen.
- 1IntroductieMaak de klasse verantwoordelijk voor haar regels
- 2UitlegScherm het veld af met een bewerking
- 3TipKies de meest beperkte bruikbare toegang
- 4UitdagingBepaal waar private toegang werkt
- 5VoorbeeldGeef informatie terug met een getter
- 6VerbandBied acties aan die bij het object passen
- 7UitdagingLezen zonder vervangen toe te staan
- 8UitlegKies een beleid voor ongeldige invoer
- 9VoorbeeldVolg begrenzing aan de bovengrens
- 10VoorbeeldControleer de begintoestand
- 11UitdagingVolg negeren in plaats van begrenzen
- 12KernpuntEen private lijst kan toch uitlekken
- 13UitdagingSluit beide ongecontroleerde routes af
- 14SamenvattingControleer de publieke interface
5Bouw en test een bruikbare klasse
12 stappen
Sla deze les op om elke Walkthrough stap voor stap te volgen.
- 1IntroductieZet een vereiste om in zichtbaar gedrag
- 2UitlegGebruik de exacte kop voor de beschrijving
- 3VoorbeeldGeef de huidige toestand als tekst terug
- 4TipMaak de beschrijving van een klok op zonder de klok te veranderen
- 5UitdagingHerstel de automatische weergave
- 6VoorbeeldKies velden op basis van de vereiste
- 7VoorbeeldStel de beginstatus vast
- 8VoorbeeldImplementeer de regel vóór de wijziging
- 9UitdagingVoorspel een reeks voordat je die uitvoert
- 10VerbandTest de gevallen die een eenvoudige uitvoering mist
- 11UitdagingOnderscheid melden van wijzigen
- 12SamenvattingBouw met een toetsbare publieke belofte
Java-klassen en objecten: oefenvragen
Set 1: Maak objecten en lees hun toestand10 Oefenvragen
Vraag 1 van 10
Parcel om meerdere pakketten te maken. Hoe heet één pakket dat wordt gemaakt terwijl het programma draait?Toon antwoordVerberg antwoord
Parcel. De klassedefinitie beschrijft de gegevens en bewerkingen voor al die objecten; het is geen andere naam voor één bepaald pakket. Een methode is een bewerking die het object kan uitvoeren.Vraag 2 van 10
Bell-object is opgeslagen in bell en ring() is een instantiemethode. Hoe moet het programma die bel laten rinkelen?Toon antwoordVerberg antwoord
ring() aan op het object waarnaar bell verwijst. De variabele vóór de punt levert de ontvanger die een instantiemethode nodig heeft. Bell.ring() noemt in plaats daarvan de klasse en kan dus niet deze bel selecteren voor een instantieaanroep.Vraag 3 van 10
private int attempts; zonder initialisator of toewijzing in een constructor. Welke waarde slaat een nieuw object op in dit veld?Toon antwoordVerberg antwoord
int-instantieveld krijgt vóór expliciete initialisatie de standaardwaarde 0. De regel dat aan een niet-geïnitialiseerde lokale variabele vóór het lezen een waarde moet worden toegewezen, geldt niet voor velden. null is de standaardwaarde voor velden van klassetypen, niet voor een int-veld.Vraag 4 van 10
new Badge("Visitor") geeft getText() null terug. Het veld is private String text;, de getter geeft het terug en de constructorbody is text = text;. Hoe moet de constructor zijn parameter text opslaan?Toon antwoordVerberg antwoord
this.text = text; schrijft de invoer naar het huidige object. Als je de toewijzing omkeert, wordt het veld dat nog null is naar de parameter gelezen; ook als je het veld aan zichzelf toewijst, blijft het oningesteld.Vraag 5 van 10
Ticket() { this(4); } en Ticket(int zones) { this.zones = zones + 1; }. Welke waarde slaat new Ticket() op in zones?Toon antwoordVerberg antwoord
Vraag 6 van 10
MinuteClock slaat uren 0–23 en minuten 0–59 op. advance() voegt één minuut toe en handelt de overgangen van uur en middernacht af. isMidnight() controleert of het 00.00 uur is. Begin op 23.57 uur en voer advance(); advance(); advance(); if (isMidnight()) { advance(); } advance(); uit. Wat is de eindtijd?Toon antwoordVerberg antwoord
Vraag 7 van 10
Lamp moet zijn eigen aan-uittoestand onthouden. Hoe moet die toestand worden gedeclareerd?Toon antwoordVerberg antwoord
Vraag 8 van 10
Bin is geschreven als int capacity; zonder toegangsmodifier. Welke toegang heeft het veld?Toon antwoordVerberg antwoord
private.Vraag 9 van 10
Session heeft private boolean active;. Aanroepers moeten die waarde kunnen controleren, maar mogen die alleen wijzigen via start() en stop(). Welke accessor past bij dit ontwerp?Toon antwoordVerberg antwoord
Vraag 10 van 10
public String toString() { return "Ready"; }. Welke tekst levert System.out.println("State: " + object); op?Toon antwoordVerberg antwoord
"Ready" samen "State: Ready" vormen. Een eigen toString() zonder argumenten vervangt de ingebouwde beschrijving met klasse en hashcode; Java voegt die ingebouwde tekst niet als extra voorvoegsel toe.Set 2: Controleer initialisatie en gecontroleerde wijzigingen10 Oefenvragen
Sla deze les op om elk antwoord te zien en elke set te oefenen.
Vraag 1 van 10
Locker heeft een veld occupied en een methode release(). Welk onderdeel van deze klasse beschrijft gedrag?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 2 van 10
Panel slaat breedte en hoogte op. De breedte kan veranderen en getArea() moet altijd de huidige oppervlakte melden. Hoe moet de oppervlakte worden weergegeven?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 3 van 10
public Sensor(int channel). Een aanroeper gebruikt new Sensor(). Waarom compileert dit niet?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 4 van 10
private int reading = 9; op. De methode is public void reset() { int reading = 0; }. Wat meldt een getter die this.reading teruggeeft na reset()?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 5 van 10
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 6 van 10
minutesSinceMidnight, terwijl de getters nog steeds dezelfde waarden teruggeven. Waarom kunnen aanroepers hun bestaande getteraanroepen behouden?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 7 van 10
setValue(25) en vervolgens setValue(8) de opgeslagen waarden na elke aanroep?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 8 van 10
Group mag maximaal vier namen bevatten. addName dwingt de limiet af, maar Group(ArrayList<String> names) slaat de meegegeven lijst rechtstreeks op en getNames() geeft de interne lijst terug. Welk ontwerp beschermt de limiet tegen wijzigingen door aanroepers?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 9 van 10
toString() zonder argumenten gebruiken?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 10 van 10
use() geeft false terug als de pas al is gebruikt; anders stelt de methode de vlag in en geeft ze true terug. reset() zet de vlag terug. toString() meldt alleen de waarde ervan. Wat geven de use-aanroepen terug in use(); println(pass); use(); reset(); use(); use();?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Set 3: Volg de toestand van objecten door langere reeksen10 Oefenvragen
Sla deze les op om elk antwoord te zien en elke set te oefenen.
Vraag 1 van 10
Marker heeft een naam en setName. Voer Marker a = new Marker("One"); Marker b = a; a = new Marker("Two"); b.setName("Three"); uit. Wat geven a.getName() en b.getName() terug?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 2 van 10
private int level = 6;. De constructor is public Beacon(int level) { this.level = level + 2; }. Wat slaat new Beacon(3) op?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 3 van 10
public Tag(String text). Welke extra constructor levert een afzonderlijke overladen variant op?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 4 van 10
scale(k) vermenigvuldigt beide afmetingen met k; area() geeft hun product terug. Voer scale(2); double saved = area(); scale(0.5); uit. Wat zijn saved en de uiteindelijke area()?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 5 van 10
Dial heeft instantieveld value en statisch veld created, beide aanvankelijk 0. Elke constructor verhoogt created één keer; turn() verhoogt alleen de waarde van de ontvanger. Voer Dial a = new Dial(); Dial b = a; b.turn(); b = new Dial(); b.turn(); b.turn(); uit. Wat zijn a.value, b.value en created?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 6 van 10
private String label;. Welke implementatie levert die waarde aan de aanroeper?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 7 van 10
setLevel begrensd tot 0–10 inclusief de grenswaarden. De constructor roept die setter aan en raise() roept setLevel(this.level + 1) aan. Begin met new Level(13) en voer raise(); setLevel(-2); raise(); raise(); uit. Wat is het eindniveau?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 8 van 10
String.format(java.util.Locale.US, "%02d:%02d", 4, 7) terug binnen een klokbeschrijving?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 9 van 10
Seat moet een tweede reservering weigeren totdat de reservering is geannuleerd. Een test controleert nu alleen de eerste succesvolle aanroep van reserve(). Welke volgende aanroep controleert de weigeringsregel het best?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 10 van 10
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Set 4: Analyseer ontwerpen en combineer de regels10 Oefenvragen
Sla deze les op om elk antwoord te zien en elke set te oefenen.
Vraag 1 van 10
Pump dit weergeven?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 2 van 10
Token heeft een numerieke waarde en addOne() verhoogt die. Voer Token a = new Token(2); Token b = a; b.addOne(); Token c = new Token(7); a = c; a.addOne(); b.addOne(); uit. Welke waarden melden a, b en c?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 3 van 10
add(int amount) declareert nu int total = amount; binnen de methode. Welke opslagwijziging maakt optellen mogelijk?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 4 van 10
Een Bucket declareert private int capacity = 2; en een lege instantielijst items. De constructor is Bucket(int capacity) { capacity = capacity; }. add geeft false terug zonder toe te voegen wanneer de lijstgrootte minstens gelijk is aan de opgeslagen capaciteit; anders voegt de methode het element toe en geeft ze true terug. snapshot() geeft new ArrayList<>(this.items) terug.
Voer Bucket b = new Bucket(4); b.add("A"); ArrayList<String> view = b.snapshot(); view.add("B"); uit. Roep daarna b.add("C") en b.add("D") aan. Wat geven deze laatste twee aanroepen terug en hoeveel elementen bevat b uiteindelijk?
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 5 van 10
Route heeft final-veld code en statisch veld created, aanvankelijk 0. De constructoren zijn Route() { this("local"); created++; } en Route(String code) { this.code = code; created++; }. Na één aanroep van elke constructor moet created twee objecten tellen. Welke correctie geeft het juiste aantal?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 6 van 10
advance() voegt één minuut toe en handelt de overgang na 24 uur af. getHour() leest het huidige uur. Voer int h = getHour(); advance(); if (getHour() != h) { advance(); } advance(); uit. Wat zijn h en de eindtijd?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 7 van 10
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 8 van 10
scale. De getter geeft this.width * this.height terug en er is geen oppervlakteveld. Waarom is dit een geldig ontwerp voor een getter?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 9 van 10
Album heeft een limiet van drie bijschriften. De constructor wijst meer dan drie bijschriften af en slaat new ArrayList<>(captions) op. getCaptions() geeft een andere kopie terug; addCaption wijst toevoegingen af wanneer de limiet is bereikt. Een aanroeper geeft twee bijschriften mee, voegt een derde toe aan de oorspronkelijke lijst, voegt een bijschrift toe aan een getterresultaat en roept daarna één keer addCaption aan. Hoeveel bijschriften bevat het Album?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 10 van 10
Door moet open() weigeren wanneer de deur op slot is. Een nieuwe deur begint gesloten en niet op slot. lock() slaagt alleen als de deur gesloten is; unlock() haalt de deur van het slot. Welke testreeks controleert de weigering terwijl de deur op slot is en daarna het succesvol openen nadat de deur van het slot is gehaald?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Kom je niet uit je eigen opgave? Huiswerkhulp
Kernbegrippen
A
Actiemethode
lend() controleert de huidige uitleenstatus, weigert een herhaalde uitlening en meldt of het uitlenen is gelukt.Alleen-lezen-eigenschap
getTitle() hebben maar geen bewerking om de titel te vervangen.Argument
new Clock(9, 5) leveren de argumenten 9 en 5 het uur en de minuut voor de nieuwe klok.B
Begrenzen tot een interval
Bereik
if-blok is gedeclareerd, eindigt bij dat blok, zodat latere code de naam niet kan gebruiken.C
Constante
static final-veld, vaak public en met een naam in UPPER_SNAKE_CASE.MAX_CELSIUS levert dezelfde bovengrens voor de temperatuur aan de klasse en haar aanroepers.Constructor
Pet kopieert de meegegeven naam, diersoort en leeftijd naar de velden van het nieuwe huisdier.Constructor zonder parameters
Clock() kan met this(0, 0) delegeren om de klok op middernacht te laten beginnen.Constructoren ketenen
this(...) een andere constructor van dezelfde klasse op hetzelfde object uitvoert.this(name, species, 0) gebruiken om initialisatie met een standaardleeftijd te hergebruiken.Constructoren overladen
D
Defensieve kopie
new ArrayList<>(this.tracks) voorkomt dat wijzigingen van buitenaf aan de lijst de interne lijst raken.E
Encapsulatie
Pet koppelt een privéveld voor de leeftijd aan controlemethoden die ongeldige wijzigingen weigeren.F
final-veld
G
Gedrag
lend() en giveBack() zodat aanroepers de uitleenstatus kunnen beheren.Getter
get.getArea() kan breedte maal hoogte berekenen, ook wanneer de klasse geen afzonderlijk oppervlakteveld opslaat.Grenswaardetest
I
IllegalArgumentException
IllegalArgumentException is een exceptie die een methode of constructor kan opwerpen om een argument af te wijzen dat de invoerregels schendt.IllegalArgumentException op te werpen voor een negatieve capaciteit voorkom je dat de constructie een ongeldig object teruggeeft.Incrementele ontwikkeling
Informatieafscherming
getHours() voor bestaande aanroepers consistent blijft.Initialisatie
new ArrayList<>() zodat daarna elementen kunnen worden toegevoegd.Instantie
Pet wanneer ze afzonderlijk zijn gemaakt.Instantiemethode
scale is een instantiemethode: a.scale(2) verandert rechthoek a, terwijl een afzonderlijke rechthoek ongewijzigd blijft.Instantievariabele
age van elk huisdier behoudt een eigen waarde, ook al staat de declaratie maar één keer in Pet.Invariant
K
Klasse
Pet houdt een naam, diersoort en leeftijd bij elkaar met bewerkingen zoals celebrateBirthday().Klassenontwerp
L
Levensduur
Lokale variabele
total binnen een berekeningsmethode bevat tijdelijk werk dat het object niet hoeft te onthouden.N
Naamafscherming (shadowing)
this.age = age; nuttig: links staat het veld en rechts de invoer.new
new begint een expressie die een object maakt, een constructor uitvoert en een referentie naar het object oplevert.new Pet("Luna", "cat", 3) maakt een huisdier en levert drie argumenten voor de begintoestand.null
null betekent dat een referentie geen object heeft om te bereiken; velden van klassetypen krijgen die waarde tenzij ze anders worden geïnitialiseerd.add op een lijstveld dat nog op null staat, mislukt omdat er geen lijstobject is gemaakt.O
Object
new-expressies zijn gemaakt, kunnen verschillende leeftijden hebben terwijl ze dezelfde klassedefinitie volgen.Ontvanger
book.lend() is de ontvanger het boek waarnaar book verwijst en waarvan de methode de uitleenvlag controleert.P
Pakkettoegang
int count; laat een andere klasse in hetzelfde naamloze pakket het veld lezen of wijzigen.Parameter
age in een huisdierconstructor ontvangt 3 wanneer de aanroep op die positie 3 meegeeft.private
private beperkt de toegang tot een lid tot code binnen de eigen klasse, zodat afzonderlijke aanroepers op het hoogste niveau de publieke interface gebruiken.pet.age = -1; mislukken in een afzonderlijke klasse Main, zodat een gecontroleerde methodeaanroep nodig is.protected
protected staat toegang vanuit hetzelfde pakket toe en beperkte toegang vanuit subklassecode buiten dat pakket.public
public geeft toegang tot een lid overal waar het declarerende type toegankelijk is, zodat aanroepers de aangeboden bewerking kunnen gebruiken.lend() laat Main om uitlening vragen terwijl het private statusveld van het boek afgeschermd blijft.Publieke interface
lend(), giveBack() en isLentOut() aanbieden terwijl de uitleenvlag private blijft.Puntnotatie
luna.getAge() vertelt Java dat het huisdier waarnaar luna verwijst zijn leeftijd moet melden.R
Recursieve constructoraanroep
Box() en Box(int) terug naar elkaar delegeren.Referentie
Pet other = luna; bevatten de twee variabelen referenties naar hetzelfde huisdier, zodat beide het kunnen bereiken.Retourwaarde
r.area() kan in een expressie worden verdubbeld; alleen de oppervlakte weergeven levert geen waarde.S
Setter
setAge(int age) kan negatieve invoer negeren zodat de opgeslagen leeftijd binnen het toegestane bereik blijft.Standaardconstructor
new Pet() een expliciete overladen constructor nodig heeft.Standaardwaarde
false; aan een lokale boolean moet een waarde worden toegewezen voordat je die kunt lezen.Statisch veld
created kan stijgen telkens wanneer de constructor een nieuwe instantie van de klasse initialiseert.Statische context
pet.getAge() levert wel een bepaald object.Statische methode
main kan Counter c maken en daarna via die referentie c.increment() aanroepen.String.format
String.format bouwt tekst op uit een opmaakstring en waarden en ondersteunt vaste breedten en decimalen.String.format met java.util.Locale.US en "%.2f" maakt 7,5 op als "7.50", ongeacht de standaardinstelling voor taal en regio.T
this
this verwijst naar het huidige object binnen instantiecode en onderscheidt de velden ervan van gelijknamige parameters.this.name = name; de nieuwe invoer naar het veld van dat specifieke huisdier.Toegangsmodifier
private, protected of public dat de toegang tot een declaratie regelt.private houdt een hulpmethode beschikbaar binnen de klasse zonder die aan andere klassen bloot te stellen.Toestand
Toestandsverloop
toString
toString() geeft de tekstrepresentatie van een object terug, zodat weergave en stringconcatenatie leesbare details kunnen tonen.toString van een klok geeft "09:05" terug, zodat het weergeven van de klok een bruikbare tijd toont in plaats van tekst met klasse en hashcode.V
Validatie
Verwacht resultaat
lend() op een uitgeleend boek is false met een ongewijzigde uitleenvlag.void
void geeft aan dat een methode geen retourwaarde levert, ook niet wanneer de methode de toestand wijzigt of uitvoer weergeeft.void hebben omdat haar taak is de opgeslagen leeftijd van de ontvanger te verhogen.#
@Override
@Override vraagt de compiler te controleren of een methodedeclaratie een methode vervangt die al door een supertype wordt geleverd.@Override boven tostring() brengt de verkeerde hoofdletter aan het licht in plaats van de automatische weergave ongewijzigd te laten.- 1Eerste Java-programma’s
- 2Voorwaarden en lussen in Java
- 3Java-methoden
- 4Lijsten, arrays en strings in Java
- 5Java-klassen en objecten
- 6Objecten, referenties en gelijkheid in Java
- 7HashMaps en collecties in Java
- 8Overerving in Java
- 9Excepties en bestanden in Java
- 10Klassendiagrammen en unittests in Java
- 11Lambda-expressies en streams in Java
Over deze les
Door StudeliFout melden
Maak je eigen Studiemateriaal
Maak van je aantekeningen, slides en documenten Leermodules, Oefenvragen, Flashcards en 6 andere tools.