Bijlagen
Hier vind je wat extra informatie die handig kan zijn, maar geen deel is van de leerstof:
Hier vind je wat extra informatie die handig kan zijn, maar geen deel is van de leerstof:
Dit document biedt een overzicht van enkele Java-specifieke concepten en syntax voor studenten die wel vertrouwd zijn met een object-georiƫnteerde programmeertaal, maar niet met Java.
Java is een sterk getypeerde taal: alle variabelen hebben types, en de compiler dwingt af dat de types overeenkomen.
Het type wordt steeds vóór de variabele geschreven: int x.
Java is ook object-georiĆ«nteerd: elke variabele is ofwel een referentie naar een object, ofwel een primitieve waarde (int, boolean, …). De speciale waarde null wordt gebruikt voor referentie-variabelen die naar geen enkel object verwijzen.
Een methode oproepen op een object gebeurt via een punt: ontvanger.methode(parameter1, parameter2)
De primitieve datatypes in Java zijn
int (32-bit integer)long (64-bit integer)short (16-bit integer)booleanfloat (single-precision)double (double-precision)char (16-bit unicode character)byte (signed! -128..127)Daarnaast is ook String een ingebouwd datatype (maar strikt genomen geen primitief type).
Strings zijn immutable: eens aangemaakt, kan geen karakters wijzigen/toevoegen/….
Tenslotte bestaan er ook zogenaamde ‘boxed’ types: Integer, Long, Short, Boolean, Float, Double, Char, Byte. Dit zijn objecten die exact ƩƩn primitieve waarde van het overeenkomstige type bevatten.
De Java compiler zorgt zelf voor boxing en unboxing:
Je kan ze dus bijna overal door elkaar gebruiken, maar het is aangeraden om, waar mogelijk de primitieve types te gebruiken.
Het voornaamste gebruik van de boxed types is als type voor ArrayLists (zie hieronder), bijvoorbeeld ArrayList<Integer> om een lijst van gehele getallen voor te stellen.
De uitvoering van een Java-programma start steeds in een methode public static void main(String[] args), die in een klasse moet staan.
Java heeft arrays; deze hebben een vaste lengte die bepaald wordt bij het aanmaken en daarna niet meer gewijzigd kan worden.
Het type van een array van type T is T[]; bij het aanmaken geef je de lengte op: new T[lengte].
De lengte kan je opvragen via het .length attribuut.
Individuele elementen vraag je op en verander je via [index]; het eerste element heeft index 0:
Een ArrayList is een collectie zoals een array, maar die groter en kleiner kan worden.
Je voegt elementen toe met add(element), en vraagt ze op via get(index).
Je moet ArrayList importeren uit het java.util package om het te kunnen gebruiken.
Een if-statement in java bevat steeds een conditie (haakjes verplicht!).
Er kunnen ook meerdere else if blokken aan toegevoegd worden,
en/of ƩƩn else-blok.
Een if-statement is geen expressie; het geeft dus geen waarde terug. Er is ook een conditionele expressie waarbij dat wel kan:
Er is ook een do-while statement, wat minstens 1 keer uitgevoegd wordt:
Bijvoorbeeld:
Een for-loop is bijna volledig equivalent aan
behalve dat je, bij de for-loop, de variabelen die in de initializer gedeclareerd worden (number in het voorbeeld hierboven) niet meer kan gebruiken na de lus (die zijn out of scope).
Een enhanced for-loop (‘foreach’) kan je gebruiken om over de elementen van een array of collectie (bijvoorbeeld een ArrayList) te itereren (meer in detail: alle klassen die de Iterable interface implementeren).
<expression> kan bijvoorbeeld een String, int of enum zijn.
break is noodzakelijk in elke case om ‘fall-through’ te vermijden.
Recentere versies van Java hebben ook een switch-expressie, met een iets andere syntax. Hier zijn geen break-statements meer nodig:
Een klasse heeft
void indien de methode geen resultaat teruggeeft. Je geeft een waarde terug via een return-statement.Een voorbeeld:
Elke publieke klasse moet in een bestand staan met dezelfde naam als de klasse, bijvoorbeeld Person.java.
Als de klasse in een package zit, moet het pad overeenkomen met dat package, bijvoorbeeld example/person/Person.java.
Een object van een klasse wordt aangemaakt via new. Daarbij wordt de constructor opgeroepen.
Tenzij een variabele een primitief type heeft, is het altijd een referentie naar het object in het geheugen (equivalent aan pointers in C/C++):
Java heeft automatische garbage collection: objecten die niet meer gebruikt worden, worden automatisch uit het geheugen verwijderd.
Java heeft 4 visibility modifiers voor klassen, velden, en methodes:
public: het element is overal toegankelijkprivate: het element is enkel toegankelijk binnen het bestand zelf (de compilation unit)protected: het element is toegankelijk voor 1) klassen binnen hetzelfde package, en 2) subklassenDaarnaast zijn er nog volgende modifiers:
static: het element is statisch, dit wil zeggen dat het geen deel uitmaakt van individuele objecten, maar van de klasse als geheel (het bestaat dus slechts 1 keer, en wordt gedeeld)final:abstract: de klasse of de methode is abstract; zie verder.Java heeft ondersteuning voor enums:
Java heeft enkelvoudige overerving: elke klasse erft over van exact 1 superklasse (indien er geen opgegeven wordt, is dat Object). Overerving van een klasse wordt aangegeven door middel van extends na de klasse-naam:
Een klasse die zelf niet rechtstreeks geĆÆnstantieerd kan worden, is abstract.
Een abstracte klasse kan abstracte methodes hebben, die door (niet-abstracte) subklassen geĆÆmplementeerd moeten worden.
Enkel niet-abstracte subklassen kunnen aangemaakt worden via new.
Een klasse kan ook meerdere interfaces implementeren. Een interface kan je zien als een abstracte klasse met enkel abstracte methodes (geen velden).
Je kan een interface gebruiken als type, op dezelfde manier als een klasse:
Je kan nakijken of een object een instantie is van een bepaalde klasse of interface via instanceof:
Over het algemeen is het gebruik van instanceof een ‘code smell’, en kijk je beter of je gebruik kan maken van polymorfisme.
In Java kan je methodes overloaden (zelfde naam maar verschillende parameter-types binnen eenzelfde klasse) en overriden (zelfde naam en parameters in super- en subklasse). Bij het overriden van een methode kan voor een object dezelfde methode dus bestaan in de klasse en in een of meerdere van de superklassen. Daarom is er een mechanisme nodig om te bepalen welke methode uiteindelijk uitgevoerd zal worden. Dat wordt in Java bepaald door
Bijvoorbeeld, neem volgende klassen en methodes:
Dan krijgen we hetvolgende:
Het statisch type van food (at compile time) is Food.
Het dynamisch type van person (at runtime) is Student.
Dus wordt de methode eat(Food food) uit de klasse Student uitgevoerd.
Wanneer zich een onvoorziene situatie voordoet, kan je dat in Java aangeven door een exception-object te gooien via throw.
Bijvoorbeeld:
De uitvoering breekt dan onmiddellijk af, en er wordt gezocht naar code die de uitzondering kan opvangen.
Exceptions opvangen doe je via een try .. catch block:
Er wordt eerst gekeken naar een try-catch blok in de methode die de methode opgeroepen heeft waarin een uitzondering gegooid werd. Is daar geen try-catch block aanwezig, wordt gekeken in de methode die die methode opgeroepen heeft, etc, tot in de main-methode.
Als er geen enkele try-catch block gevonden wordt die de uitzondering kan afhandelen, stopt het programma.
Hierboven gebruikten we unchecked exceptions; alle unchecked exceptions erven over van de klasse RuntimeException. Java heeft ook checked exceptions; deze erven over van de klasse Exception. Checked exceptions moeten vermeld worden in de methode-hoofding, en code die de methode oproept moet ze opvangen of ze opnieuw vermelden in de methode-hoofding.
Checked exceptions maken het vaak lastig om iets te programmeren, en de voorkeur wordt tegenwoordig vaak gegeven aan unchecked exceptions.