Skip navigation

Java Tutorial

Dit is een eerste aflevering van een nederlandstalige tutorial voor de programmeertaal Java. Ze zou nog wel wat opgekuist mogen worden, en uitgebreid, maar ik zet ze hier on-line voor mocht er interesse zijn.

Kernconcepten

Java is een object georienteerde programeertaal met sterke typechecking. De belangrijkste kernbegrippen zijn objecten en klassen. Bij conventie begint de naam van een klasse steeds met een hoofdletter, en de broncode van een enkele klasse wordt opgeslagen in een bestand met dezelfde naam als de klasse (ook met hoofdletter) en de extensie .java . Hier is een voorbeeld van een zeer eenvoudige klasse.

public class MyClass {

}

Zoals je ziet bestaat de definitie van een klasse uit het sleutelwoord ‘class’ gevolgd door de naam van de klasse, en het lichaam van de klasse (het gedeelte van ‘{’ tot en met ‘}’). Het sleutelwoord klasse kan voorafgegaan worden door een of meer modifiers.

De modifier ‘public’ bepaalt de zichtbaarheid van onze klasse. Publieke klassen zijn voor elke andere klasse zichtbaar.

Wanneer deze klasse opgeslagen wordt in een bestand MyClass.java kan ze met behulp van de java-compiler (meestal het commando ‘javac’) gecompileerd worden naar java-bytecode. In deze vorm kan ze geladen worden in een java virtuele machine.

vb.

$ vi MyClass.java
$ javac MyClass.java
$ ls
MyClass.class MyClass.java

De java compiler zet elke klasse om in een bestand met extensie .class .

Binnen een klasse kunnen we velden, methoden, constanten en binnenklassen definieren. Hier is een voorbeeld van een methode:

public class MyClass {
public void myUselessMethod() {
}
}

De signatuur van een methode bestaat opnieuw uit een of meer modifiers, het return-type (hier ‘void’ omdat deze methode geen waarde teruggeeft), de lijst van parameters, en het lichaam van de methode.

Datatypes

Onmisbaar in procedurale talen zijn variabelen. Variabelen kunnen een waarde bevatten. Het type van een variabele bepaalt welke waarden in de variabele opgeslagen kunnen worden. Wanneer we een variabele definieren, moeten we opgeven van welk datatype deze variabele is.

In java kennen we tree categorieen van datatype, primitieve types enerzijds, en klassen anderzijds. De primitieve types zijn:

boolean waarheidswaarde true of false
char karakter (16-bit UNICODE)

byte 8 bits getal (+ of -)
short 16 bits getal
int 32 bits getal
long 64 bits getal

float enkele precisie vlottende komma getal
double dubbele precisie vlottende komma getal

We zouden bijvoorbeeld onze methode van een variabele kunnen voorzien:

public class MyClass {
public int myUselessMethod() {
int var = 0;
var++; //var = var + 1;
return var;
}
}

Wanneer we nu deze methode uitvoeren zal een variabele van het type int gecreerd worden, met waarde 0. Vervolgens verhogen we de waarde met een, en de nieuwe waarde geven we terug aan de oproepende methode. Merk op dat elk commando wordt afgesloten met een puntkomma.

Objecten

We kunnen ook variabelen declareren met als type de naam van een klasse. Zo bevat de java API een klasse String. We kunnen dus een variable declareren

String eenString;

Wanneer we nu aan deze variabele een waarde willen toekennen, dan spreken we van een object van het type String dat we aan de variabele toekennen. Er is dus een subtiel verschil tussen een klasse en een object. Je kan zeggen dat de klasse het type is en objecten van die klasse waarden van dat type.

In een klasse kunnen we een structuur definieren, maar er geen toestand aan toekennen. Dat kan pas wanneer we een object van die klasse maken.
Een voorbeeld.

public class DakPan {
private int breedte;
private int hoogte;

public void setBreedte(int b) {
breedte = b;
}

public void setHoogte(int h) {
hoogte = h;
}
}

public class DakPannenFabriek {
public DakPan maakGroteDakpan() {
DakPan dp = new DakPan();
dp.setBreedte(100);
dp.setHoogte(100);
return dp;
}

public DakPan maakKleineDakpan() {
DakPan dp = new DakPan();
dp.setBreedte(50);
dp.setHoogte(50);
return dp;
}
}

We zien hier een aantal dingen. De klasse dakpan heeft twee velden gekregen, breedte en hoogte. De inhoud van deze velden bepaalt de toestand van een DakPan object. Het type is numeriek (int), en we plaatsen een extra modifier ‘private’ omdat we niet willen dat andere klassen zich rechtstreeks met onze interne toestand bemoeien. In plaats daarvan voorzien we twee methoden om deze velden in te stellen (zogenaamde mutators of setters).

De klasse DakPannenFabriek bevat twee methoden die elk een object van het type DakPan teruggeven. Om aan zo’n DakPan object te geraken gebruik je de new-operator, gevolgd door de naam van de klasse en twee haakjes. (Vanwaar de haakjes komt later, al lijkt het wel erg sterk op het oproepen van een methode). Dit object kunnen we dan met de = operator toekennen aan een variabele van het type DakPan. (net zoals in int n = 0;).

Het verschil tussen een variabele en een veld is dat een variabele die binnen een methode gedeclareerd is zijn waarde niet behoudt doorheen verschillende aanroepen van die methode. Velden bepalen de huidige toestand (waarde) van een object, doorheen zijn levensloop. Zij behouden dus tijdens de hele levensloop van het object hun waarde.

Verder zien we dat een methode van een object oproepen gebeurt met een punt gevolgd door de methode en zijn argumenten. Voor het teruggeven van een waarde bij het oproepen van een methode gebruik je het sleutelwoord ‘return’.

Arrays

In java dienen we een verschil te maken tussen arrays (tabellen) van primitieve types, of van objecten. Een array gedraagt zich zelf in sommige opzichten als een primitief type, en in andere opzichten als een object. Hier demonstreren we het gebruik van arrays.

int[] array; //declareer dat array een variable is van het type array-van-integer
array = new int[5]; //ken aan array een waarde toe, namelijk een array die 5 ints kan bevatten.
array[0] = 1; //eerste element
array[4] = 999; //laatste element
int lengte = array.length; //op deze manier kunnen we de lengte van een array opvragen, let op! geen haakjes.

We zouden nu ook het volgende kunnen proberen.

DakPan[] pannen = new DakPan[5]; //Reserveer een tabel voor 5 dakpannen.
pannen[0].setBreedte(50); //Dit lukt niet, java meldt een NullPointerException.

Deze code geeft een foutmelding, wat is er gebeurd? In het eerste geval, wanneer we ‘new int[5]’ oproepen worden de 5 posities in de tabel geinitialiseerd met de waarde 0. Welke waarde krijgen de 5 posities in onze dakpannen tabel?

Het antwoord is ‘null’, dit sleutelwoord staat voor de waarde ‘geen object’. Wanneer we een methode uitvoeren op een variabele die geen object bevat, dan krijgen we een foutmelding, een NullPointerException. Zo lossen we dit op:

DakPan[] pannen = new DakPan[5]; //Reserveer een tabel voor 5 dakpannen.
pannen[0] = new DakPan();
pannen[0].setBreedte(50); //Dit lukt wel!

Controlestructuren

We introduceren de while en for lus, en de if-statement aan de hand van een voorbeeld.

public class DakPan {
private int breedte;
private int hoogte;

public void setBreedte(int b) {
if (breedte < 1) {
breedte = 1;
} else {
breedte = b;
}
}

public void setHoogte(int h) {
if (hoogte < 1) {
hoogte = 1;
} else {
hoogte = h;
}
}
}

public class DakPannenFabriek {
public DakPan[] bestelling(int aantalGrote, int aantalKleine) {
DakPan[] bestelling = new DakPan[aantalGrote+aantalKleine];
for (int teller = 0 ; teller < aantalGrote ; teller++) {
bestelling[teller] = maakGroteDakpan;
}
while(aantalKleine > 0) {
bestelling[aantalGrote+aantalKleine - 1] = maakKleineDakpan();
aantalKleine–;
}
}

/*
*Methode is nu privaat, we willen alleen dakpannen maken wanneer er een bestelling geplaatst is.
*/
private DakPan maakGroteDakpan() {
DakPan dp = new DakPan();
dp.setBreedte(100);
dp.setHoogte(100);
return dp;
}

private DakPan maakKleineDakpan() {
DakPan dp = new DakPan();
dp.setBreedte(50);
dp.setHoogte(50);
return dp;
}
}

Input/output

Over input en output in java valt heel veel te vertellen, we treken hier twee methoden uit onze hoed om de lezer te kans te geven te experimenteren.
Om iets uit te schrijven naar het standaard output kanaal kan je de methode System.out.println(…) gebruiken. Om te lezen van standaard in gebruik je volgende code:

plaats bovenaan het bestand, nog voor de klasse-definitie:

import java.io.*;

Om vervolgens een lijn tekst van het toestenbord te lezen gebruik je volgende code:

BufferedReader reader = new BufferedReader(new InputStreamReader (System.in));
String input = reader.readLine();

Uivoerbaar programma

Om een programma uitvoerbaar te maken heb je een plaats nodig waar het programma begint. Dit is de main-methode. Plaats in een klasse een methode met signature

public static void main(String[] args)

(Trek je voorlopig nog niet te veel aan van de static modifier.)

Na compilatie kan je het programma uitvoeren:

$java EenUitvoerbareKlasse

Merk op dat we geen extensie (.class) opgeven. Mogelijk zal java klagen dat hij de klasse niet kan vinden, in dat geval moet je het classpath instellen. Dit kan vanop de commandline:

$java -cp ./ EenUitvoerbareKlasse

of in unix-achtige omgevingen met

$export CLASSPATH=./

Referenties

Onmisbaar : de javadoc van de standaard API
*http://java.sun.com/j2se/1.5.0/docs/api/

‘The java tutorial’ van Sun
*http://java.sun.com/docs/books/tutorial/java/TOC.html

Vragen en opmerkingen : arne(punt)brasseur(apestaart)gmail(punt)com