NTNU-logo-leksjoner.png (8 Kb)
Variabler, datatyper og uttrykk
Vuokko-Helena Caseiro, Institutt for datateknologi og informatikk (IDI), NTNU
Lærestoffet er utviklet for faget Programmering i Java

Innhold

Variabeldeklarasjoner

Læreboka fortsetter med et kapittel om variabler og uttrykk. Dette er de minste byggeklossene i Java. For den som har programmert tidligere i andre språk er dette sannsynligvis kjent stoff. Vi gjennomgår dette og kontrollstrukturer i de neste to kapitlene for deretter å ta fatt på klasser og objekter, som er de viktigste elementene i objektorienterte språk, slik som Java.

For å forstå hva en variabel er, kan vi tenke på en beholder eller boks som kan inneholde en eneste verdi. Det fins flere typer slike bokser (dvs. det fins flere datatyper), f.eks. int-bokser og boolean-bokser. Type boks bestemmer hva slags verdi som kan ligge oppi boksen. En int-boks kan kun inneholde heltall (altså f.eks. 5 eller 899 eller 0 eller -343), og med den begrensning at heltallet ikke må være for "stort" (oppta for stor plass) - det må være mellom ca. minus 2 milliarder og 2 milliarder. En boolean-boks kan kun inneholde en av to sannhetsverdier, true eller false. Hvis man prøver å legge f.eks. et 4-tall oppi en boolean-boks vil kompilatoren protestere.

Det er vi som programmerere som sørger for at variabler blir laget. Det gjør vi med en variabeldeklarasjon:

alder1.gif

Her har vi deklarert en variabel av type int og kalt den alder. Når vi kjører programmet vil det da bli opprettet en lagringsplass ("boks") som kan inneholde heltallsverdier (bare en verdi av gangen) og som heter alder. Vi gir variabelen et navn for at det skal være mulig å snakke om den og bruke den i programmet.

Vi kan også deklarere en variabel og gi den en verdi straks (initiere den, som vi ofte sier):

alder2.gif

Læreboka summerer opp alle de primitive datatypene i Java:

Det er altså litt å velge på når det gjelder tall. Men hvis vi skal jobbe med heltall, tar vi nesten alltid int, fordi det er så innarbeidet som den tradisjonelle heltallstypen ("integer" betyr jo da også "heltall"). Og vi tar double når vi skal ha desimaltall. Bare unntaksvis trenger vi å gjøre noen sak ut av hvor store verdier som får plass i en variabel. Det er sjelden det er noen vits i å tenke på at "en int tar dobbelt så stor plass i datamaskinen som en short, kunne jeg ikke nøyd meg med en short her?" De datamaskinene vi vanligvis lager programmer på har massevis av minne, og hvilken datatype vi velger for et par variabler er av nesten ingen betydning.

Bruk av variabler

Hva er det så vi kan bruke en variabel til? Egentlig bare to ting: Gi den en verdi (legge noe i boksen), eller "konsultere" den (se etter hva som ligger i boksen). Hvordan gjør vi disse to tingene?

Før vi svarer på det, vil vi si litt om metoder generelt. For det er i metodene at vi gjør ting; det er i metodene at ting virkelig "skjer" i Java-programmer. Hva er så en metode? Foreløpig vil vi bare si at en metode er en navngitt (f.eks. "main") mengde setninger, - en metode er en oppskrift for å gjøre et eller annet. Når vi kjører metoden, får vi gjort det som står i oppskriften.

En setning er en instruksjon (en kommando) til datamaskinen: Det aller første eksemplet vi hadde på en setning var følgende "utskriftsetning":

System.out.println("Hei verden!");

Legg merke til det typiske semikolonet som avslutter setningen. Effekten er at vi får skrevet ut "Hei verden!" til skjermen.

Tilbake til variablene og de to tingene vi ønsker å kunne gjøre med dem. For det første: hvordan gir vi en variabel en verdi? Svar: Ved å bruke en tilordningssetning. Den har grunnformen

variabelnavn = uttrykk;

Effekten er å legge verdien av uttrykket oppi variabelen. Vi kan f.eks. ha alder = 34; .

Legg straks merke til at "=" ikke betyr "lik"! Vi kan f.eks. ikke skrive 34 = alder; - i tilordningssetninger er det en essensiell forskjell på venstreside og høyreside.

Et helt komplett eksempel som du kan kjøre (BareEnVariabel.java):

class BareEnVariabel {
  public static void main(String[] args) {
    int alder = 12;
    alder = 34;
  }
}

Vi kan illustrere kjøring av dette programmet slik:

BareAlder.gif

Men programmet vårt er ikke særlig "uttrykksfylt"; når vi kjører det kan vi ikke se at det skjer noe som helst! I dette eksempelprogrammet ønsker vi også å kunne se skrevet ut til skjermen hva som ligger i variabelen til forskjellige tider. Det kan vi gjøre ved å føye til noen utskrifter (BareEnVariabelPlussUtskrift.java):

class BareEnVariabelPlussUtskrift {
  public static void main(String[] args) {
    int alder = 12;
    System.out.println("etter deklarasjon er alder = " + alder);
    alder = 34;
    System.out.println("etter tilordning er alder = " + alder);
  }
}

Det er svært viktig å ha det helt klart for seg at de fire setningene utføres i den rekkefølgen de står i ("sekvensielt"), en etter en:

BareEnVariabelPlussUtskrift.gif

Så var det spørsmålet om hvordan vi "konsulterer" variabler. Vi har ennå ikke svart generelt på dette. Men vi har allerede greid å få skrevet ut innholdet av variabelen i utskriftvinduet, og det var jo enslags konsultasjon. Legg merke til hvordan vi gjorde det: Vi nevnte variabelens navn (og bak kulissene ble så i dette spesielle tilfellet heltallet gjort om til en tekststreng og kunne skrives ut). Generelt er svaret: Det er nok å nevne variabelens navn. Det er underforstått at det er verdien av variabelen vi er interessert i. Unntaket til denne regelen er venstresiden i tilordningssetningen: vi nevner et variabelnavn men vil ikke konsultere men endre verdien av den nevnte variabelen.

Eksempel: I Eldring.java nedenfor ser vi at i setningen alder = alder + 4; behandles variabelen alder forskjellig i venstresiden (endring) og høyresiden (konsultasjon). Setningen utføres i to trinn. Først beregnes høyresiden: til den "konsulterte" verdien av alder (12) legges 4; resultatet er 16. Og deretter utføres tilordningen: 16 blir lagt i alder.

class Eldring {
  public static void main(String[] args) {
    int alder = 12;
    System.out.println("etter deklarasjon er alder = " + alder);
    alder = alder + 4;
    System.out.println("etter tilordning er alder = " + alder);
  }
}

Du kan vanskelig gå videre før du har forstått fullt ut hvordan en variabel benyttes som en beholder for en verdi, og hvordan vi i programmene våre kan bruke den verdien som til enhver tid finnes i beholderen ved å bruke variabelens navn. Så de som trenger det må lese stoffet om variabler her og i læreboka grundig. Og de må prøve ut det de leser praktisk, i små program.

Navngitte konstanter

Det er mulig å lage variabler som ikke kan endre verdi. Disse blir i boka kalt for navngitte konstanter. Kompilatoren vil protestere hvis du har en navngitt konstant i venstresiden av tilordningssetningen. Les på s. 57 - 58 i læreboka hvordan navngitte konstanter deklareres vha. final. Les også hvorfor vi ofte kan ønske å bruke navngitte konstanter, f.eks. final double CM_PER_TOMME = 2.54;.

Aritmetiske uttrykk

Vi har allerede sett noen eksempler på (aritmetiske) uttrykk, så som 12, alder, alder + 4. Et uttrykk er en sammensetning av operatorer (f.eks. +, *), variabler og konstanter. Det bygges opp bit for bit: Vi tar noen små uttrykk og setter dem sammen vha. en operator, og dette uttrykket inngår så, evt. sammen med andre uttrykk, i et enda større uttrykk osv.

Eksempel: Anta at alder og ansiennitet er heltallsvariabler: Da er følgende et uttrykk:

(alder * (-alder)) / (3 + ansiennitet)

For å gjøre strukturen i dette uttrykket klarere (håper vi!), kan vi tegne det opp som et tre (treet står på hodet):

tre.gif

Du kan kontrollere at dette uttrykket har åtte deluttrykk medregnet hele uttrykket: det er fire "blader" (ytterpunkter) som hver for seg er uttrykk; videre er det tre deltrær som svarer til -alder, alder * (-alder), 3 + ansiennitet; og til slutt er det hele uttrykket. Legg også merke til at vi har respektert at *, +, og / tar to argumenter hver, mens den -'en vi har brukt, kun tar ett argument.

Skopet til en lokal variabel

En lokal variabel er en variabel som er deklarert inni en metode, står det i læreboka (s. 56). Og det vel greit nok på et vis, for i de fullstendige program-eksemplene vi hittil har sett er det alltid i metoden main() at vi gjør alt, inkludert variabel-deklarasjoner. Det står også at skopet til en lokal variabel er resten av den blokken der variabelen er deklarert. Skopet er det stykke program der vi kan bruke variabelen. Når vi kjører programmet er det der variabelen "eksisterer"; variabler har altså ikke noe evig liv.

Men hva betyr egentlig dette med "resten av den blokken der variabelen er deklarert"? For oss, som bare har en metode main() og som ennå ikke har lært å lage flere blokker, betyr det at deklarasjonsområdet til en variabel i main() er resten av main(). Den blokken det er snakk om er main()' metodekropp. F.eks. AldersUtskrift.java:

AldersUtskrift.gif

Om ikke lenge skal vi begynne å lage litt mer kompliserte klasser. Hvordan vil det da ha seg med skopet til lokale variabler? Vi gir nå en forsmak på ting vi skal lære skikkelig lengre ut i kurset. Husk at vi lager programmer ved å lage klasser. En klasse kan se slik ut når den har to objektvariabler og to metoder (MinKlasse.java - kan bare kompileres, ikke kjøres):

MinKlasse.gif

Vi har her merket av skopene til de fem lokale variabler. Vi har tatt med noen objektvariabler for å vise at ikke alle variabler er lokale variabler. Men foreløpig kan vi glemme objektvariablene. Vi har tatt med en if-setning for å ha et eksempel på blokk som ikke er en metodekropp.

Navn

Når vi programmerer, skaper vi våre egne ting, så som variabler, klasser og metoder. Vi må selv navngi våre skapninger.

Det eksisterer selvsagt eksakte regler for hva som er lovlige navn (se Språkkjerne s. 52): Vanlige tall og tegn er lov. Blanktegn er ikke lov. Et tall først i navnet er ikke lov. Norske tegn og andre spesielle lokale tegn går fint, men i bestemte tilfeller, nærmere bestemt i navngiving av en klasse, bør de unngås (s. 52).

Det fins også konvensjoner for navngiving (se første punkt i listen på s. 170 eller vedlegg C): Stor forbokstav i navn på klasser, liten forbokstav i navn på metoder og variabler. Hvis et navn består av flere ord, brukes stor forbokstav i andre ord og tredje ord osv. Eksempler:

Når vi omtaler metoder (f.eks. her i leksjonene) har vi ofte et parentespar etter navnet; vi skriver f.eks. main() i stedet for bare main. Utifra bare navnet kan man da se om det er snakk om en klasse (stor forbokstav), eller en metode (liten forbokstav samt parentespar etter navnet) eller en variabel (liten forbokstav).

Tilslutt: vi bør bestrebe oss på å lage navn som er "gode" for oss mennesker. Det bør være mening i navnene. Se "lyspæren" på s. 52.

Typeomforming mellom talltyper

Hva om vi prøver å bruke et uttrykk som involverer flere forskjellige talltyper? Talltyper har vi jo så mange av, kan det ikke lett bli tull? Vi tar et eksempel (TypeSjekk.java) der vi tar for oss flere varianter av denne problematikken på en gang:

class TypeSjekk {
  public static void main(String[] args) {
    int integer1 = 3;
    int integer2 = 4;
    double double1 = 4.5;

    System.out.println(integer1 / double1);
    System.out.println(integer1 / integer2);
    System.out.println(integer1 / (double) integer2);
  }
}

Vi har her deklarert tre variabler, to av typen int og en av typen double. Så utfører vi tre divisjoner mellom dem, og skriver ut resultatene. Utskriften blir slik:

0.6666666666666666
0
0.75

Vi tar de tre resultatene en etter en: Dersom vi deler en int på en double vil Java automatisk skjønne at dette må bli et desimaltall, og vi får resultatet som desimaltall.

Dersom vi deler to int med hverandre, så er konvensjonen at det utføres heltallsdivisjon (se "lyspæren" s. 70). I vårt tilfelle blir svaret 0, ikke 0.75 (resten blir borte).

Dersom vi vil dividere to heltall, men ønsker resultatet som desimaltall, benytter vi en eksplisitt typeomforming eller casting på minst en av dividend og divisor. Det er dette vi har gjort i den tredje og siste linjen: vi har satt (double) foran divisor. Da omformes det heltallet til double, og vi får på sett og vis den samme situasjonen som det første tilfellet. Legg merke til at innholdet i variabelen integer2 ikke blir endret ved castingen.

Innlesing og utskrift vha. JOptionPane

Vi vil bruke klassen JOptionPane for å kommunisere med brukeren av programmet. Les om JOptionPane i delkapittel 2.6 Vi vil kalle JOptionPane-metoden

showInputDialog()
for å lese inn en tekst, og JOptionPane-metoden
showMessageDialog()
for å skrive ut en tekst. Disse to metodene tar seg altså bare av tekster, som er av datatypen String. Men vi har jo mange andre datatyper, f.eks. har vi sett også int, double, char og boolean. For disse datatypene må vi til med omforming. Hvis f.eks. en tekst (f.eks. "948") kan anses som et heltall (nemlig 948), gjør vi om teksten til et heltall slik:
int heltallet = Integer.parseInt(enTekstSomKanTolkesSomEtHeltall);
I eksemplet Arealberegning2 s. 64 - 65 er det double det omformes til.

Både JOptionPane, Integer og Double er klasser. Vi skal senere (f.o.m. leksjon 5) lære å lage klasser selv. Da vil vi også lære at vi må lage et objekt av en klasse før vi kan kalle metodene i klassen. Men her lager vi jo ikke noe objekt av verken JOptionPane, Integer eller Double? Det er fordi de metodene vi kaller fra disse klassene er såkalte klassemetoder, - de er ikke (objekt)metoder. (Se evt. s. 234. Det er det lille ordet static som gjør metodene til klassemetoder.)

For at vi enkelt skal kunne bruke klassemetodene i JOptionPane "importerer" vi dem ved å skrive
import static javax.swing.JOptionPane.*;
Opphavsrett: Forfatteren og Stiftelsen TISIP