Java. Deel I

ArticleCategory:

Software Development

AuthorImage:

[Jose M. Fernández]

AuthorName:

Jose M. Fernández

AboutTheAuthor:

Abstract:

Dit is de eerste in een reeks van artikelen over het programmeren in Java. Dit eerste deel beschrijft de programmeertaal Java zelf, zijn belangrijkste eigenschappen en de plaatsen waar men verdere informatie kan vinden.

ArticleIllustration:

[Illustratie]

ArticleBody:

Inleiding

Dit is de start van een artikelenreeks die de programmeertaal Java en zijn ontwikkelomgeving zal beschrijven. Allereerst zal ik proberen om onderwerpen als de geschiedenis van de taal, magnetron, wasmachines en dergelijke te vermijden (als iemand daarin is geïnteresseerd; hier zijn talloze publicaties van, zelfs in de betere literatuur). Ik zal ook proberen Duke, de mascotte van Java te vermijden. Duke is een klein figuurtje met een aardbeienneus en driehoekig lijf die zijn handen beweegt op de maat van de Marimba en me doet denken aan oude Amerikaanse SF-films.

Het fenomeen Java is ook een beetje hype. Ieder zichzelf respecterend computerblad schrijft erover, een oneindige rij softwarebedrijven verkoopt ontwikkelhulpmiddelen voor Java-applets en iedere website heeft wel één of meerdere van die applets draaien (applet = een kleine of lichte applicatie).

Met deze reeks wil ik proberen wat meer diepgaand de programmeertaal te behandelen. In zijn geheel. Dit is dan wel betrekkelijk eenvoudig voor de basisonderdelen; de constante evolutie van deze taal maakt het echter weer moeilijker.

Het doel van de eerste reeks is om de taal in zijn geheel te beschrijven. Hierdoor zijn we later in staat om speciale onderwerpen met wat meer diepgang te behandelen, zoals: applets, netwerk-gerelateerde programmering, JDBC, beans etc.

Ik moet hier wel benadrukken dat Java een taal is die niet specifiek gemaakt is voor het programmeren van applets op web-pagina's, hoewel het zijn populariteit hier wel aan te danken heeft, maar algemeen inzetbaar is. We kunnen niet bij dit aspect blijven hangen want voor dat doel zijn er nog genoeg alternatieven die misschien zelfs beter geschikt zijn dan Java-applets.

Dit eerste artikel is wat meer theoretisch en wat minder op de praktijk gericht. In het volgende artikel zullen we de eigenschappen van de taal zelf en zijn ontwikkelomgeving bespreken. Pas aan het eind komen er voorbeelden van Java programma's aan de orde.

Oorsprong

Java is in een periode van 18 maanden bedacht door James Gosling, Patrick Naughton, Chris Warth, Ed Frank en Mike Sheridan die bij Sun Microsystems Inc. werkten in 1991. Tussen 1992 en 1995 werkten Bill Joy, Arthur van Hoff, Jonathan Payne, Frank Yellia en Tim Lindolm aan het vervolmaken van dit product.

Uit de datums kunnen we concluderen dat Java ongeveer tegelijkertijd met het World Wide Web (WWW) is ontstaan. Tot voor 1991 had Tim Berners Lee de HTML-taal immers nog niet ontwikkeld.

De syntaxis van Java lijkt op C en de objectgeoriënteerde eigenschappen lijken op C++. Java is een coherente en consistente programmeertaal.

De gelijkenis met C en C++ kan de indruk wekken dat Java een versie van C++ is die geschikt is gemaakt voor het Internet. Er zijn echter significante theoretische en praktische verschillen. Vooral omdat Java het objectgeoriënteerde paradigma ten opzichte van C++ verbetert en verfijnt.

Het Internet heeft Java succes gebracht en algemeen bekend gemaakt. Omgekeerd heeft Java ook een grote invloed gehad op het Internet. Het heeft er voor gezorgd dat er nog meer nuttige dingen over het Internet getransporteerd kunnen worden (dynamische, onafhankelijk executeerbare programma's).

Het verkrijgen en installeren van Java

Er zijn een aantal onmisbare hulpmiddelen voor het programmeren in Java. Overigens zal ik het in deze reeks altijd hebben over de GNU/Linux omgeving (voor het geval iemand de draad kwijtraakt):

De huidige implementatie van ELF voor Linux vereist kernel versie 1.2.13 of hoger.

Ik zal gebruik maken van de JDK-omgeving (Java Development Kit) samen met Netscape versie 2.0.14 of hoger en een tekst-editor, bijvoorbeeld Xemacs. Het werk gebeurt onder Xwindows. Hoewel niet altijd noodzakelijk, is het wel nodig bij het ontwikkelen van applets en programma's met een grafische gebruikers interface.

De JDK distributie kan bij de volgende website worden gedownload:
http://www.blackdown.org/java-linux.html
Vanaf deze site kan men de dichtstbijzijnde of snelste mirror kiezen om het ophalen te versnellen. Een paar maanden geleden was de laatste versie JDK-1.1.3 (gebruikt in dit artikel) maar bij mijn laatste bezoek was dit al 1.1.9. Als we alles ophalen is het ongeveer 24 Mb! Alleen ophalen wat we nodig hebben komt neer op ongeveer 12 Mb (en veel geduld!).

Na het uitpakken met gunzip zijn we klaar om verder te gaan.

Normaliter zetten we de distributie in de directory /usr/local waar aldus een subdirectory JDK1.1.3 zal worden aangemaakt. En daarbinnen:

doc Officiële documentatie in HTML formaat.

demo Demo Java programma's

lib Programmabibliotheken

bin Hier staan de juiste ontwikkelhulpmiddelen van de JDK.

In de lib directory zit het bestand classes.zip (laat unzip hier niet op los), hierin zitten alle gecompileerde klassen waar Java gebruik van -kan- maken.

In de startdirectory zit het bestand src.zip. Hierin zit alle broncode uit classes.zip. Deze code kan echter niet worden gecompileerd en is slechts ter lezing ende vermaak meegeleverd.

Ontwikkelomgeving

Zoals reeds vermeld zitten de ontwikkelhulpmiddelen in bin:

javac: Java compiler die de broncode omzet in bytecodes.

Java: de interpretator. Voert Java bytecodes uit.

jre: een "uitgeklede" Java interpretator voor diegenen die niet alle opties gebruiken of nodig hebben.

appletviewer: test applets en voert ze uit.

jdb: debugger (foutzoeker).

javap: disassembler voor bytecode bestanden die gecompileerd zijn door Java.

javadoc: documentatie generator. Maakt HTML bestanden met documentatie over alle klassen, interfaces, constructors en methoden. Het genereert ook een hiërarchisch overzicht van alle klassen en een index van alle elementen.

javah: hulpmiddel om platformafhankelijke methoden (in C) aan Java toe te voegen.

jar: archiveert Java klassen en broncode in jar archief bestanden.

javakey: hulpmiddel bij het gebruik van digitale handtekeningen.

updateAWT: werkt in een applicatie de namen bij van AWT methoden die veranderd zijn sinds AWT1.02.

Om zonder problemen met de huidige directorystructuur te kunnen werken wordt geadviseerd om het pad /usr/local/JDK1.1.3/bin aan je omgevingsvariabele PATH toe te voegen. Als je het voor alle gebruikers op het systeem wilt doen dan moet je het toevoegen aan het bestand /etc/profile.

Eigenschappen

Voordat we doorgaan moeten we onszelf de vraag stellen "Wat is Java eigenlijk?". Het antwoord kan worden gevonden in het bijgeleverde JDK handboek. Java is twee dingen: het is een programmeertaal én het is een platform.

Java is een hogere programmeertaal met de volgende eigenschappen (details volgen nog):

Het eerst wat opvalt is dat Java wordt geinterpreteerd. Dit ondanks het feit dat broncode eerst moet worden gecompileerd om bytecode te genereren (op zich al een lagere programmeertaal) die op zijn beurt moet worden geinterpreteerd op diverse machines.

Dankzij Java kunnen we "slechts één keer broncode schrijven, vervolgens altijd uitvoeren". We kunnen hiermee een Java programma compileren op de ene machine, om het vervolgens uit te voeren op een compleet andere machine met een compleet andere architectuur maar die wel een Java Virtuele Machine (JVM) heeft draaien. Een Java programma kan bijvoorbeeld op een Windows NT machine worden gecompileerd en vervolgens probleemloos (in theorie althans) draaien op een Sun Ultra Solaris.

In het algemeen is een platform de omgeving van hardware en software waarop een applicatie draait. Bij Java echter, is het platform de software omgeving waarin het draait. Ieder Java platform moet op zijn beurt op een echt platform draaien.

Een Java platform bestaat uit twee componenten:

JVM is een abstractie van een computer waarbinnen gecompileerde Java programma's kunnen draaien. Het is ontworpen met eenvoud en kleinschaligheid in het achterhoofd, opdat het op zowat alles zou kunnen draaien. Deze eenvoud maakt het mogelijk om het op alle mogelijke omgevingen te implementeren, waarmee een algemene softwarelaag wordt gecreëerd binnen een zeer heterogeen netwerk (zoals het Internet). Hiermee worden een groot aantal problemen met betrekking tot overdraagbaarheid opgelost. Zoals men zich voor kan stellen kan dit heel veel van de enorme groei van deze technologie verklaren.

Toch moet de virtuele machine niet gezien worden als een pure softwarelaag. Zoals de naam al aangeeft probeert het een volledige machine te zijn. Langzaam maar zeker zullen we Javachips op de markt zien verschijnen die gebruikt zullen worden voor echte (en géén virtuele) Java machines, kredietkaarten, TV decoders etc.

Java's applicatie interface (API) bestaat uit een grote verzameling software componenten die programmeer-hulpmiddelen ter beschikking stellen zoals een grafische gebruikersinterface (GUI). De API is onderverdeeld in bibliotheken (in Java terminologie packages). Dankzij deze packages kunnen we Java gebruiken voor veel meer dan alleen maar het bouwen van applets. We kunnen hiermee bijvoorbeeld Webservers maken, of proxies, mail servers en alles wat verder met Internet te maken heeft.

De onderverdeling van deze bibliotheken is als volgt:

Naast deze basis interfaces zijn er ook nog: 3D-extensies, mobiele communicatie, animaties etc.

Zoals reeds eerder vermeld heeft Java een groot aantal eigenschappen die we nu nader gaan bekijken:
Eenvoud: Java heeft altijd een beperkt aantal mogelijkheden voor het uitvoeren van een taak. Het heeft alle functionaliteit van een krachtige programmeertaal, maar zonder de minder courante en complexe uitbreidingen die daar normaal gesproken mee gepaard gaan. Java heeft de syntaxis van C/C++ geërfd en veel objectgeoriënteerde mechanismen van C++. Iedere programmeur die bekend is met C/C++ zal geen moeite hebben met het aanleren van Java. Ondanks de overeenkomsten mist Java een aantal C/C++ karakteristieken, zoals:
  • Rekenen met verwijzingen (pointers)
  • Registers (struct)
  • Type definities (typedef)
  • Macro's (define)
  • De verplichting geheugen op te ruimen (free)
  • Geen overerving van meer dan één klasse
  • Geen herdefinities (overload) van operatoren
  • Geen structuren in unions
Objectoriëntatie: Java is van de grond af nieuw ontworpen. Hierdoor is zijn benadering van objectoriëntatie bruikbaar, praktisch en vrij van vervuiling. Het objectmodel van Java is eenvoudig in het gebruik.
Gedistribueerd: Men heeft het op grote schaal toepassen van TCP/IP voorzien en hier het ontwerp op afgestemd. Het benaderen van een bestand is net zo makkelijk als het benaderen van informatie op het netwerk.
Robuust: Java heeft een strikte typering. Hierop kan men reeds tijdens het compileren controleren. Verdere controles worden in run-time uitgevoerd. Het geheugenbeheer is volautomatisch. De interpretator geeft alle geheugen weer vrij van objecten die niet meer gebruikt worden. Java stelt een aantal objectgeoriënteerde uitzonderingen (exceptions) ter beschikking. In een goed geschreven programma handelt het programma zelf alle run-time fouten af.
Platform onafhankelijk: Het hoofddoel van de ontwerpers van Java was: "slechts één keer broncode schrijven, vervolgens altijd overal uitvoerbaar en op ieder gewenst moment". Java wordt eenmalig naar bytecode gecompileerd. Deze bytecode is machine onafhankelijk. De code is erop ontworpen om op iedere machine uitgevoerd te kunnen worden met een machinespecifiek run-time systeem (interpretator).
Veiligheid: De noodzaak van gedistribueerde informatie vereist een hoge graad van beveiliging op de client systemen. Java levert reeds beveiliging in zijn run-time omgeving:
  • Een bytecode controle
  • Beschikbaarheid van geheugen tijdens executie
  • Beveiliging op bestandstoegang
Hoewel de compiler slechts correcte bytecode aan kan maken wordt nog eens extra gecontroleerd door de interpretator om te zien of code is aangepast (expres of per ongeluk) tussen het moment van compilatie en interpretatie. Verder controleert de interpretator de beschikbaarheid van geheugen. Java is wat dat betreft één van de meest veilige applicaties op een systeem.
Overdraagbaarheid: Naast de basis overdraagbaarheid van Java, is er nog wel wat meer nodig om ook onafhankelijk te zijn van de architectuur. Hiervoor heeft Java een overdraagbaarheids-standaard: integers zijn altijd integers, de grafische interface is een abstractie van windows en daardoor onafhankelijk van de onderliggende architecturen (Unix, PC of Mac).
Geïnterpreteerd: Om één van de hoofddoelen van Java te bereiken, platform onafhankelijkheid, genereert de compiler intermediaire code (bytecode). Dit kan op ieder systeem met de juiste interpretator worden uitgevoerd. Dit paradigma geeft bedenkingen over de snelheid van het systeem. Juist vanwege deze bedenkingen zijn de makers bij het ontwerpen van de bytecode uitgegaan van eenvoud en het zo simpel mogelijk kunnen vertalen naar machinecode, zodat de hoogste snelheid in uitvoering kan worden behaald.
Multi-threaded: Het is heel eenvoudig om applicaties te maken die verschillende taken parallel en betrouwbaar uitvoeren.
Dynamisch: Java zal niet direct proberen alle modules van een applicatie aan elkaar te linken. Dit gebeurt pas tijdens het uitvoeren van het programma. Hiermee verkrijgt men dynamisch gelinkte code, veilig en gemakkelijk.
Na deze lange "toespraak" (het meeste is terug te vinden in de officiële Java documentatie) kan men zich afvragen hoe het is gesteld met Java in de wereld van GNU/Linux. We hebben het al eerder gehad over de verkrijgbaarheid van JDK onder Linux, wat slechts een commerciële implementatie van Sun is (echter: vrij te distribueren).

Er zijn pakketten als de compiler GUAVAC, te gebruiken met een GPL-licentie die alle Java broncode probleemloos kan compileren. De virtuele machine KAFFE, onder Berkeley-licentie, is ook het vernoemen waard. Deze projecten zijn in een vergevorderd stadium, hoewel ze nog steeds de klassebibliotheken van Sun als aanvulling nodig hebben (die momenteel vrij zijn te distribueren) om een complete ontwikkelomgeving te verkrijgen.

Andere projecten, nog in de beginfase, hebben als doel een snelle en visueel ingestelde ontwikkelomgeving te creëren.

Tenslotte zij het gezegd dat er een enorme beweging op het Internet op gang is gekomen met betrekking tot Java en GNU, waarbij het er om gaat om, onafhankelijk van Sun, een complete, vrij distribueerbare ontwikkelomgeving te creëren. Hiermee is het belang van Java wel aangegeven en als de hype voorbij is, dan ben ik er zeker van dat daar er wat van blijft hangen (sterker nog, ik denk dat er veel zal overblijven).

Een eerste programma in Java

Laten we, na deze algemene eigenschappen van de taal, eens een blik werpen op een echt programma. Zoals reeds gezegd in de introductie wil ik dingen als hello world voorbeelden zoveel mogelijk vermijden. Laten we in plaats daarvan een programma nemen dat een vierkant tekent van iedere gewenste grootte (iets moeilijker, maar niet te):

Bestand Cuadro.Java
class Cuadro {
public static void main (String args[]) {
        int l ,a;
        if (args.length == 2) {
            l = Integer.valueOf(args[0]).intValue();
            a = Integer.valueOf(args[1]).intValue();
         }
         else {
          l= 20;
          a= 15;
         }
          for (int i=l; i>0; i--){
            System.out.print("*");
            }
            System.out.print("\n");
            for (int i= a-2; i>0; i--){
             System.out.print("*");
               for(int j=l-2; j>0; j--) {
                  System.out.print(" ");
                  }
                  System.out.print("*\n");
                  }
                for (int i=l; i>0; i--){
                System.out.print("*");
                }
              System.out.print("\n");
           }
}
De naam die we geven aan het bestand met de broncode is in Java belangrijk. Het definieert een eenheid van compilatie. Het bestand kan definities bevatten van meerdere klassen. De compiler verwacht .java (4 letters) als extensie op de naam. Sommige systemen (DOS en Windows 3.1) ondersteunen dit dus niet.

In het voorbeeld is de naam van het bestand identiek aan de klasse. Dit is geen toeval, alle code moet in een klasse zitten. De conventie schrijft verder voor dat de naam van de klasse overeen moet komen met de naam van het bestand waarin de code staat. Sterker nog, Java maakt zelfs onderscheid tussen hoofd- en kleine letters.

Type het volgende in op de commandoregel om het programma te compileren:

> javac Cuadro.java

De compiler zal, als alles goed gaat, het bestand Cuadro.class aanmaken waarin natuurlijk de bytecode wordt gezet. Het kan nu direct worden uitgevoerd door de interpretator met het commando:

> java Cuadro

Gecompileerde broncode wordt automatisch in een archief geplaatst met dezelfde naam als de klasse, zodat deze naam overeenkomt met de bestandsnaam van het archive.class bestand.

Ondanks de eenvoud van ons voorbeeld programma Cuadro.java, geeft het een inzicht in de basisstructuur van Java en de principes erachter.

Merk allereerst op dat dit voorbeeld geen applet is dat kan worden aangeroepen vanuit een HTML bestand maar een zelfstandig programma, uit de voeren door de interpretator als commando.

De eerste regel van het programma is:

class Cuadro {
Het eerste woord is een door de taal gereserveerd token en geeft de definitie aan van een nieuwe klasse, Cuadra genaamd - Spaans voor vierkant. Tussen de twee accolades {} die volgen komt de precieze definitie van de klasse. Merk op dat in Java alles zich afspeelt binnen klassen.

De volgende regel:

public static void main (String args[]) {
bevat de definitie van een methode main(). Alle Java programma's starten het uitvoeren met main() (net als in C/C++). Laat ik even een paar details bespreken die nodig zijn om het voorbeeld te begrijpen (in volgende artikelen gaan we hier dieper op in).

Het keyword public geeft het bereik aan van de methoden binnen deze klasse. Het zegt dat de methode gebruikt kan worden door code buiten deze klasse. static geeft aan dat de methode direct aangeroepen kan worden. De klasse hoeft niet eerst te worden aangemaakt. void geeft aan dat de methode geen waarde retourneert. Het doorgeven van parameters aan een functie of methode doet men binnen de haken () die achter de naam van de methode staan. In dit geval accepteert main() als parameter een matrix van instanties van de klasse String.

Het is duidelijk dat de code in een methode ook wordt omsloten met accolades {}. Daarna de volgende regel:

 int l, a ;
waarin twee integer variabelen worden gedeclareerd. Iedere variabele moet worden gedeclareerd voordat hij kan worden gebruikt. Merk op dat iedere instructie eindigt met een puntkomma ";".

De verdere code implementeert een klein algoritme dat het volgende doet:

  1. Test of het juiste aantal argumenten is gegeven.
    If (args.length==2)
    
  2. Indien er parameters zijn dan worden ze toegewezen aan integer variabelen:
      l = Integer.valueOf(args[0]).intValue();
      a = Integer.valueOf(args[1]).intValue();
    
  3. Indien dit niet het geval is dan krijgen de variabelen standaard waarden:
      l = 20;
      a = 15;
    
  4. De rest van het programma bevat alleen maar instructies, nodig voor het tekenen van het vierkant op het scherm. Hierbij gaat het vooral om:
    System.out.print()
    

    Waarbij print() de gegeven parameter afdrukt. System is een reeds gedefinieerde klasse die toegang regelt tot het systeem en out is de uitvoerstroom die verbonden is met het console. De constructie:

    for (int i=l; i>0; i--)
    

    gedraagt zich zoals je zou verwachten indien je ervaring hebt met C/C++ of andere talen.

Een aardig stukje huiswerk voor de lezer is om uit te vinden hoe dit voorbeeld te compileren en uit te voeren. Ook de overdraagbaarheid hiervan kan men testen door de gecompileerde code te draaien op meerder platformen, zoals: Linux en Windows 95 (beschouw dit echter niet als een zegen!) en te constateren dat het overal op dezelfde manier wordt uitgevoerd.

Samenvatting

We hebben kunnen snuffelen in de basismogelijkheden van Java als programmeertaal. We zijn maar net begonnen met programmeren en nog lang niet aan het eind. Toekomstige artikelen zullen dieper op de taal in gaan. Het eerstvolgende artikel zal ingaan op de definities, de verschillende typen variabelen, basis instructies, klassen etc. Kortom, de specificatie van de taal in grote lijnen.

Ieder artikel zal vergezeld gaan van een lijst met referenties, publicaties en URL's waarop deze reeks artikelen is gebaseerd.