Osa 1

Muuttujat ja ohjelmien kielellistäminen

Keskeinen käsite ohjelmoinnissa on muuttuja. Muuttujaa kannattaa ajatella lokerona, johon voi tallettaa annetun tyyppistä tietoa. Tiedolla on aina tyyppi. Tyyppejä ovat esimerkiksi teksti eli merkkijono (String), kokonaisluku (int), liukuluku (double) eli desimaaliluku, ja totuusarvo (boolean). Muuttujaan asetetaan arvo yhtäsuuruusmerkillä (=).

int kuukausia = 12;

Yllä olevassa lauseessa asetetaan kokonaisluku-tyyppiä (int) olevaan muuttujaan nimeltä kuukausia arvo 12. Lause luetaan "muuttuja kuukausia saa arvon 12".

Muuttujan arvo voidaan yhdistää merkkijonoon +-merkillä seuraavan esimerkin mukaisesti.

String teksti = "sisältää tekstiä";
int kokonaisluku = 123;
double liukuluku = 3.141592653;
boolean totuusarvo = true;

System.out.println("Tekstimuuttuja: " + teksti);
System.out.println("Kokonaislukumuuttuja: " + kokonaisluku);
System.out.println("Liukulukumuuttuja: " + liukuluku);
System.out.println("Totuusarvo: " + totuusarvo);

Tulostus:

Esimerkkitulostus

Tekstimuuttuja: sisältää tekstiä Kokonaislukumuuttuja: 123 Liukulukumuuttuja: 3.141592653 Totuusarvo: true

Loading

Muuttujien nimet ovat uniikkeja, eikä kahdella muuttujalla saa olla ohjelmassa samaa nimeä. Seuraavassa esimerkissä oleva ohjelma on virheellinen, koska ohjelmassa yritetään luoda kahteen kertaan muuttujaa nimeltä pii. Muuttujan luominen tapahtuu kun muuttuja esitellään ensimmäistä kertaa.

public class Esimerkki {
    public static void main(String[] args) {
        double pii = 3.14;
        double pii = 3.141592653;

        System.out.println("Piin arvo on: " + pii);
    }
}

Muuttujan tyyppi kerrotaan kun muuttuja esitellään ensimmäistä kertaa. Kun muuttujaan asetetaan uusi arvo, ei muuttujan tyyppiä enää kerrota.

int luku = 10;
System.out.println(luku);
luku = 4;
System.out.println(luku);
Esimerkkitulostus

10 4

Muuttujaan asetetun arvon muuttaminen

Muuttuja on olemassa sen esittelyhetkestä lähtien, ja sen arvo säilyy kunnes muuttujaan asetetaan toinen arvo. Muuttujan arvon muuttaminen onnistuu lauseella, jossa on muuttujan nimi, yhtäsuuruusmerkki, ja muuttujan uusi arvo. Huomaa että muuttujan tyyppi kirjoitetaan vain kun muuttuja esitellään ohjelmassa ensimmäistä kertaa.

int luku = 123;
System.out.println("Muuttujan arvo on " + luku);

luku = 42;
System.out.println("Muuttujan arvo on " + luku);

Tulostus:

Esimerkkitulostus

Muuttujan arvo on 123 Muuttujan arvo on 42

Tarkastellaan edellisen ohjelmakoodin suoritusta askel askeleelta. Kun muuttuja esitellään ohjelmakoodissa ensimmäistä kertaa, eli sekä muuttujan tyyppi (tässä int) että sen nimi (tässä luku) kerrotaan tietokoneelle, tietokone luo muuttujaa varten "nimetyn lokeron". Tämän jälkeen yhtäsuuruusmerkin oikealla puolella oleva arvo kopioidaan tähän nimettyyn lokeroon.

Kun ohjelmakoodissa viitataan muuttujaan sen nimellä — tässä halutaan tulostaa merkkijono "Muuttujan arvo on " sekä muuttujan luku arvo, muuttujan luku arvo haetaan sen nimellä löytyvästä lokerosta.

Kun muuttujaan asetetaan arvo (tässä luku = 42), tarkistetaan ensin löytyykö muuttujan nimistä lokeroa. Jos lokero löytyy, uusi arvo kopioidaan lokeroon vanhan arvon tilalle ja vanha arvo katoaa. Jos muuttujan nimellä ei löydy lokeroa, ohjelman suoritus päättyy virheilmoitukseen tai ohjelmaa ei voida käynnistää.

Seuraavaksi ohjelmakoodissa viitataan taas muuttujaan sen nimellä — tässäkin halutaan tulostaa merkkijono "Muuttujan arvo on " sekä muuttujan luku arvo. Toimitaan kuten normaalisti, eli haetaan muuttujan luku arvo sen nimellä löytyvästä lokerosta.

Kuten huomaat, ohjelman lopputilanteessa muuttujan alkuperäinen arvo on kadonnut. Muuttuja voi sisältää kerrallaan aina vain yhden arvon.

Muuttujan tyyppi pysyy

Kun muuttujan tyyppi on kertaalleen määritelty, ei sitä voi enää muuttaa. Totuusarvoa ei siis voi esimerkiksi asettaa kokonaislukutyyppiseen muuttujaan, eikä totuusarvomuuttujaan voi asettaa kokonaislukua.

boolean onnistuukoKokonaisLuvunAsetus = false;
onnistuukoKokonaisLuvunAsetus = 42; // Ei onnistu

int luku = 10;
onnistuukoKokonaisLuvunAsetus = luku; // Ei myöskään onnistu

Poikkeus kuitenkin löytyy: liukulukutyyppiseen muuttujaan voi asettaa kokonaisluvun, sillä Java osaa muuttaa kokonaisluvun liukuluvuksi asetuksen yhteydessä.

double liukuluku = 0.42;
liukuluku = 1; // Onnistuu

int luku = 10;
liukuluku = luku; // Onnistuu myös

Liukulukua ei kuitenkaan voi asettaa kokonaislukuun. Tämä johtuu siitä, että ohjelmointikielen suunnittelijat yrittävät suojella ohjelmoijaa tietoa kadottavilta ohjelmointivirheiltä.

int luku = 4.2; // Ei onnistu

double liukuluku = 0.42;
luku = liukuluku; // Ei myöskään onnistu

Muuttujan nimentä

Muuttujien nimentä on oleellinen osa ohjelman kuvausta. Tarkastellaan kahta esimerkkiä.

double a = 3.14;
double b = 22.0;
double c = a * b * b;

System.out.println(c);
Esimerkkitulostus

1519.76

double pii = 3.14;
double sade = 22.0;
double pintaAla = pii * sade * sade;

System.out.println(pintaAla);
Esimerkkitulostus

1519.76

Edellä olevat kaksi esimerkkiä sisältävät täsmälleen saman toiminnallisuuden ja tuottavat saman tulostuksen. Toinen esimerkeistä on kuitenkin paljon ymmärrettävämpi. Kyseessä on ympyrän pinta-alan laskevan ohjelman koodi. Ensimmäisellä rivillä määritellään piin arvo, toisella rivillä ympyrän säde, ja kolmannella rivillä lasketaan pinta-ala. Tämän jälkeen pinta-ala tulostetaan.

Muuttujan nimeämistä rajoittavat tietyt ehdot.

Muuttujan nimessä ei saa olla tiettyjä erikoismerkkejä, kuten huutomerkkejä (!). Välilyönti ei ole sallittu, sillä se erottaa komentojen osat toisistaan. Välilyönti kannattaa korvata camelCase<-tyylillä, jolloin nimi muistuttaneeKamelia. Huom! Muuttujien nimien ensimmäinen kirjain kirjoitetaan aina pienellä:

int camelCaseMuuttuja = 7;

Numeroita voidaan käyttää muuttujan nimessä, kunhan nimi ei ala numerolla. Nimi ei myöskään voi koostua pelkistä numeroista.

int 7muuttuja = 4; // Ei sallittu!
int muuttuja7 = 4; // Sallittu, mutta ei kuvaava muuttujan nimi

Muuttujan nimi ei saa olla jo entuudestaan käytössä. Tällaisia nimiä ovat mm. aikaisemmin määritellyt muuttujat ja Javan valmiit komennot, kuten System.out.print ja System.out.println.

int camelCase = 2;
int camelCase = 5; // Ei sallittu -- muuttuja camelCase on jo käytössä!

Muuttujien nimissä ei tule myöskään käyttää ääkkösiä. Voit korvata ääkköset aakkosilla, eli muuta ä -> a ja ö -> o.

Sallittuja muuttujien nimiä

  • kuukaudenViimeinenPaiva = 20
  • ensimmainenVuosi = 1952
  • nimi = "Essi"

Virheellisiä muuttujien nimiä

  • kuukauden viimeinen päivä = 20
  • 1paiva = 1952
  • varo! = 1910
  • 1920 = 1

Muuttujan tyyppi kertoo muuttujan mahdollisista arvoista

Muuttujan tyyppi kerrotaan muuttujan esittelyn yhteydessä. Esimerkiksi merkkijonon "teksti" sisältävä merkkijonomuuttuja luodaan lauseella String merkkijono = "teksti"; ja kokonaisluvun 42 sisältävä kokonaislukumuuttuja luodaan lauseella int luku = 42;.

Muuttujan tyyppi määrää arvot, joita muuttuja voi saada. String-tyyppiset muuttujat saavat arvokseen merkkijonoja, int-tyyppiset muuttujat saavat arvokseen kokonaislukuja, double-tyyppiset muuttujat saavat arvokseen liukulukuja, ja boolean-tyyppiset muuttujat saavat arvokseen totuusarvoja.

Kunkin tyypin mahdolliset arvot ovat siis rajattuja. Esimerkiksi merkkijonomuuttuja ei voi sisältää kokonaislukuarvoa, eikä liukuluku voi sisältää totuusarvoa. Alla on listattu käyttämillemme muuttujille niiden mahdolliset arvoalueet.

TyyppiEsimerkkiSallitut arvot
Kokonaisuluku, eli intint luku = 4;Kokonaislukumuuttuja voi sisältää kokonaislukuja, joiden arvot ovat välillä -2147483648 ja 2147483647.
Liukuluku, eli doubledouble luku = 4.2;Liukulukumuuttuja sisältää desimaalilukuja, joiden suurin mahdollinen arvo on noin 21023 Kun desimaaliluku esitetään liukuluvun avulla, voi luku olla epätarkka; liukuluvulla ei pysty esittämään mitä tahansa desimaalilukua. Taustasyihin palataan kurssilla Tietokoneen toiminta.
Merkkijono, eli StringString teksti = "Hei!";Merkkijonomuuttuja voi sisältää merkkijonoja. Merkkijonot rajataan hipsuilla.
Totuusarvo, eli booleanboolean tosi = true;Totuusarvomuuttuja sisältää joko arvon true eli totta tai arvon false eli epätotta.

Erityyppisten muuttujien lukeminen käyttäjältä

Ohjelmiemme käyttämissä tekstipohjaisissa käyttöliittymissä syötteen lukeminen käyttäjältä tapahtuu aina merkkijonona, sillä käyttäjä kirjoittaa syötteen tekstinä. Merkkijonon lukeminen käyttäjältä on jo tuttua — siihen käytetään Scanner-apuvälineen tarjoamaa nextLine-komentoa.

import java.util.Scanner;

public class Ohjelma {

    public static void main(String[] args) {
        Scanner lukija = new Scanner(System.in);

        System.out.println("Kirjoita tekstiä ja paina enter ");
        String teksti = lukija.nextLine();
        System.out.println("Kirjoitit " + teksti);
    }
}
Esimerkkitulostus

Kirjoita tekstiä ja paina enter teksti Kirjoitit teksti

Muunlaiset syötteet kuten kokonaisluvut, liukuluvut ja totuusarvot luetaan myös tekstinä, mutta ne muunnetaan Javan tarjoamilla apuvälineillä annetun muuttujan tyyppiseksi.

Kokonaisluvun lukeminen

Merkkijonon muuntaminen kokonaisluvuksi tapahtuu komennolla Integer.valueOf, jolle annetaan parametrina muunnettavan luvun sisältämä merkkijono.

String lukuMerkkijonona = "42";
int luku = Integer.valueOf(lukuMerkkijonona);

System.out.println(luku);
Esimerkkitulostus

42

Scanneria käytettäessä lukeminen ja muuntaminen asetetaan yleensä sisäkkäin. Tämä tapahtuu seuraavasti.

import java.util.Scanner;

public class Ohjelma {

    public static void main(String[] args) {
        Scanner lukija = new Scanner(System.in);

        System.out.println("Kirjoita luku ");
        int luku = Integer.valueOf(lukija.nextLine());
        System.out.println("Kirjoitit " + luku);
    }
}
Esimerkkitulostus

Kirjoita luku 42 Kirjoitit 42

Loading

Kokeile toteuttamasi ohjelman toimintaa myös syötteillä, jotka eivät ole lukuja. Ohjelman pitäisi hajota, sillä se ei tiedä miten sellaiset syötteet, jotka eivät ole lukuja, pitäisi muuttaa luvuiksi. Opimme Ohjelmoinnin jatkokurssilla menetelmiä muunmuassa tällaisten poikkeustilanteiden käsittelyyn.

Liukuluvun lukeminen

Merkkijonon muuntaminen liukuluvuksi tapahtuu komennolla Double.valueOf, jolle annetaan parametrina muunnettavan luvun sisältämä merkkijono.

String lukuMerkkijonona = "42.42";
double luku = Double.valueOf(lukuMerkkijonona);
System.out.println(luku);
Esimerkkitulostus

42.42

Kuten kokonaislukujen tapauksessa, Scanneria käytettäessä lukeminen ja muuntaminen asetetaan yleensä sisäkkäin. Tämä tapahtuu seuraavasti.

import java.util.Scanner;

public class Ohjelma {
    public static void main(String[] args) {
        Scanner lukija = new Scanner(System.in);
        System.out.println("Kirjoita luku ");
        double luku = Double.valueOf(lukija.nextLine());
        System.out.println("Kirjoitit " + luku);
    }
}
Esimerkkitulostus

Kirjoita luku 1234.2 Kirjoitit 1234.2

Liukulukutyyppiseen muuttujaan voi lukea myös kokonaisluvun. Tällöin luku muunnetaan liukulukutyyppiseksi automaattisesti. Alla oleva esimerkki näyttää edellisen ohjelman toiminnan kun käyttäjä syöttää kokonaisluvun.

Esimerkkitulostus

Kirjoita luku 18 Kirjoitit 18.0

Loading

Totuusarvon lukeminen

Merkkijonon muuntaminen kokonaisluvuksi tapahtui komennolla Integer.valueOf ja merkkijonon muuntaminen liukuluvuksi tapahtui komennolla Double.valueOf. Komento valueOf esiintyy myös merkkijonon muuntamisessa totuusarvoksi — tämä tehdään komennolla Boolean.valueOf.

Totuusarvotyyppiset muuttujat voivat saada arvokseen vain true eli totta tai false eli epätotta. Kun merkkijonoa muunnetaan totuusarvotyyppiseksi, merkkijonon tulee olla "true" mikäli totuusarvon arvoksi halutaan true. Kirjoitusasulla ei ole väliä, eli myös "TRue" muuttuu totuusarvoksi true. Muut merkkijonot muuntuvat totuusarvoksi false.

import java.util.Scanner;

public class Ohjelma {
    public static void main(String[] args) {
        Scanner lukija = new Scanner(System.in);
        System.out.println("Kirjoita totuusarvo ");
        boolean arvo = Boolean.valueOf(lukija.nextLine());
        System.out.println("Kirjoitit " + arvo);
    }
}
Esimerkkitulostus

Kirjoita totuusarvo enpäs! Kirjoitit false

Esimerkkitulostus

Kirjoita totuusarvo TRUE Kirjoitit true

Esimerkkitulostus

Kirjoita totuusarvo true Kirjoitit true

Loading

Yhteenveto

Alla vielä yhteenveto:

import java.util.Scanner;

public class Ohjelma {
    public static void main(String[] args) {
        Scanner lukija = new Scanner(System.in);
        String teksti = lukija.nextLine();
        int kokonaisluku = Integer.valueOf(lukija.nextLine());
        double liukuluku = Double.valueOf(lukija.nextLine());
        boolean totuusarvo = Boolean.valueOf(lukija.nextLine());

        // jne
    }
}
Loading
Pääsit aliluvun loppuun! Jatka tästä seuraavaan osaan:

Muistathan tarkistaa pistetilanteesi materiaalin oikeassa alareunassa olevasta pallosta!