Javassa taulukot ovat olioita. Ne siis muiden olioiden tapaan luodaan new-operaatiolla (myös ns. taulukon alustajalla, kts. alla). Muiden oliomuuttujien tapaan taulukkomuuttuja on viittaustyyppiä. Kun taulukko-olio on luotu, sen kokoa ei voi muuttaa, mutta taulukkomuuttuja voi ohjelman suorituksen aikana saada arvokseen eri taulukko-olioita, esimerkiksi eri mittaisia taulukoita!
Taulukon koko on siis taulukko-olion ominaisuus, ei taulukkomuuttujan.
Taulukon indeksit alkavat aina nollasta ja indeksien arvot voivat olla vain int-tyyppisiä (byte, short, ja char kelpaavat, ne muutetaan automaattisesti int-tyyppisiksi, mutta long on itse muutettava eksplisiittisellä tyyppimuunnoksella!).
int[] tauluA; int[] tauluB = null; int[] tauluC = new int[4]; int[] tauluD = {3, 5, 9, 11}; int[] tauluE = {};tahdotaan sanoa, että
Taulukkomuuttujan määrittelyssä käytettävät []-sulkeet voidaan sijoittaa joko tyypin tai muuttujan jälkeen. Esimerkiksi määrittelyt
String[] args; String args[];tarkoittavat täsmälleen samaa: muuttuja args voi joskus saada arvokseen taulukon, jonka komponentit ovat String-olioita. Ensimmäinen muoto ilmaisee selkeämmin, että muuttujan tyyppi on taulukko!
Myös useampiulotteiset taulukot ovat mahdollisia (kyseessä ovat oikeastaan yksiulotteiset taulukot, joiden komponentteina on taulukoita!):
int[][] matriisiA = new int[2][2]; int[][] matriisiB = { {1, 2}, {3,4} }; double[][][] avaruus = new double[100][100][100]; short[][][] mikälie = {{{1,2},{3,4}}, {{5,6},{7,8}} }; boolean[][][][][] böö = new boolean[2][3][54][2][9];Huom: on syytä tietää (mutta näin ei pidä itse tehdä!), että määrittelyt:
double avaruus[][][] = new double[100][100][100]; double[] avaruus[][] = new double[100][100][100]; double[][] avaruus[] = new double[100][100][100];tarkoittavat aivan samaa kuin edellisen esimerkinkin määrittely muuttujalle avaruus!
Kuten edellä todettiin, taulukkotyypillä ei ole pituutta eli komponenttien määrää, mutta taulukko-olio on koko olemassaolonsa ajan vakiokokoinen. Taulukko-olion pituus löytyy kentästä length (luokista ja kentistä luvussa 4):
double[] dTau = new double[10]; // nyt dTau.length == 10 dTau = new double[100]; // nyt dTau.length == 100Niinpä on mahdollista välittää vaikkapa parametrina vaihtelevankokoisia taulukoita (joiden komponenttityyppi on sama!):
private static void ykköstä(double[] tau) { for (int i=0; i<tau.length; ++i) tau[i] = 1.0; }Huom: Taulukon pituus saadaan kentästä length, String-olion pituus metodilta length()!
Taulukon komponenttityyppi voi olla mikä tahansa Javan tyyppi, myös viittaustyyppi! Niinpä siis alkeistyyppien lisäksi vaikkapa String on mahdollinen ja myös mikä tahansa itse tehty luokka!
Taulukko siis on itse olio ja se luodaan new-operaatiolla (tai alustajalla). Jos taulukon komponentit ovat olioita, myös ne on luotava kukin erikseen new-operaatiolla! (Oliokomponentin alkuarvo on tyhjä olio, null. Myös alkeistyyppiset komponentit saavat oletusalkuarvon, kts. luku 4.)
Esimerkkejä taulukon käytöstä (TKayttoa.java):
public class TKayttoa { public static void main(String[] args) { int[] itauA; int[] itauB = null; int[] itauC = new int[10]; String[] mjtau = new String[20]; PikkuVarasto[] vtau = new PikkuVarasto[100]; // taulukko, jonka joka alkioksi // voidaan asettaa PikkuVarasto-olio!! itauC[2] = 7; itauC[0] = itauC[2]; itauC[9] = itauC[2] - 89; itauA = itauB; itauA = new int[30]; itauB = itauA; mjtau[0] = "Miau"; for (int i=1; i<6; ++i) mjtau[i] = mjtau[i-1]+mjtau[0]; for (int i=0; i<6; ++i) System.out.println(mjtau[i]); for (int i=0; i<100; ++i) vtau[i] = new PikkuVarasto(i, "Olut"); // i:nteen varastoon // arvoksi i System.out.println(vtau[7]); vtau[7].vieVarastoon(vtau[42].paljonkoOn()); System.out.println(vtau[7]); } }Ohjelma tulostaa:
Miau MiauMiau MiauMiauMiau MiauMiauMiauMiau MiauMiauMiauMiauMiau MiauMiauMiauMiauMiauMiau (Olut: 7.0) (Olut: 49.0)
Jos oletetaan äskeiset esimerkkimäärittelyt:
int[] itauA; int[] itauB = null; int[] itauC = new int[10]; String[] mjtau = new String[20]; PikkuVarasto[] vtau = new PikkuVarasto[100]; // taulukko, jonka joka alkioksi // voidaan asettaa PikkuVarasto-olio!!seuraavat lauseet ovat virheellisiä:
itauA[2] = 7; //Kääntäjä: Variable itauA may not have been initialized. itauB[2] = 7; //Tulkki: java.lang.NullPointerException itauC[10] = 3; //Tulkki: java.lang.ArrayIndexOutOfBoundsException itauC[9] = 89.9; //Kääntäjä: Incompatible type for =. Explicit cast needed to // double to int. itauA = new double[30]; //Kääntäjä: Incompatible type for =. Can't convert double[] // to int[]. itauB = itauA; //Kääntäjä: Variable itauA may not have been initialized. //---- vtau[7].vieVarastoon(321); //Tulkki: java.lang.NullPointerException
public class Parat { public static void main(String[] args) { for (int i=0; i < args.length; ++i) System.out.println(i+". parametri: "+args[i]); } }Kun sovellus käynnistetään komennolla:
java Parat Olipa kerran kissa.tulostuu:
0. parametri: Olipa 1. parametri: kerran 2. parametri: kissa."Merkkijonot" tässä yhteydessä tarkoittavat välilyönnein erotettuja välilyöntejä sisältämättömiä merkkien jonoja.
(Java-terminologiassa taulukon komponenttityypiksi (component type) kutsutaan mitä tahansa tyyppiä josta taulukko on muodostettu. Alkiotyypiksi (element type) kutsutaan sellaista komponenttityyppiä, joka ei ole taulukko. Jokaisesta taulukkotyypistä löytyy lopulta alkiotyyppi. Sitä kutsutaan koko taulukon alkiotyypiksi. Samalla tavoin käytetään käsitteitä komponentti ja alkio!)
Esimerkki matriiseista:
int[][] a = new int[2][3]; int[][] b = {{9, 21, -2}, {2, 7, 19}}; int[][] c = new int[2][3]; for (int i=0; i<2; ++i) for (int j=0; j<3; ++j) a[i][j] = i+j; for (int i=0; i<2; ++i) for (int j=0; j<3; ++j) c[i][j] = a[i][j] + b[i][j]; for (int i=0; i<2; ++i) { for (int j=0; j<3; ++j) System.out.print(c[i][j]+" "); System.out.println(); }Ohjelma tulostaa:
9 22 0 3 9 22Taulukkotyyppi siis määrää vain taulukon komponenttityypin, se ei määrää taulukon kokoa. Jokainen viittaustyyppinen komponenttiolio luodaan erikseen. Kun taulukon komponenttityyppi on taulukkotyyppi, eri komponenteiksi voidaan luoda eri kokoisia taulukko-olioita:
int[][] c = new int[2][]; // c on int[][]-tyyppinen taulukkomuuttuja, jonka // komponentteina on nyt kaksi int[]-taulukkoa: // c[0] ja c[1] // luodaan komponenttiolioiksi eri kokoiset taulukot: c[0] = new int[5]; c[1] = new int[2]; // käytetään taulukkoja: for (int i=0; i < c[0].length; ++i) c[0][i] = 100-5*i; for (int i=0; i < c[1].length; ++i) c[1][i] = 5*i - 100; for (int i=0; i < c.length; ++i) { for (int j=0; j < c[i].length; ++j) System.out.print(c[i][j]+" "); System.out.println(); }Ohjelma tulostaa:
100 95 90 85 80 -100 -95Toinen esimerkki:
int[][][][] t = new int[3][][][]; t[1] = new int[4][][]; t[1][3] = new int[3][]; t[1][3][0] = new int[2]; t[1][3][2] = new int[5]; t[1][3][0][1] = 8; t[1][3][2][3] = -123;Piirrä kuva tästä!
public class TauluMetossa { public static void main(String[] args) { int[] b = teePerustaulu(20); for (int i=0; i < b.length; ++i) System.out.print(b[i]+" "); System.out.println(); } private static int[] teePerustaulu(int koko) { int[] tulos = new int[koko]; for (int i=0; i < tulos.length; ++i) tulos[i] = i; return tulos; } }Ohjelma tulostaa:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19Mutkikkaammatkin tapaukset ovat mahdollisia (IhmeTauluMetossa.java):
public class IhmeTauluMetossa { public static void main(String[] args) { String[][] c = abcMatriisi('A', 5); for (int i=0; i < c.length; ++i) { for (int j=0; j < c[i].length; ++j) System.out.print(c[i][j]+" "); System.out.println(); } } private static String[][] abcMatriisi(char merkki, int kpl) { String[][] tulos = new String[kpl][kpl]; for (char m=merkki; m < merkki+kpl; ++m) for (char n=merkki; n < merkki+kpl; ++n) tulos[m-merkki][n-merkki] = ""+ m+n; return tulos; } }Ohjelma tulostaa:
AA AB AC AD AE BA BB BC BD BE CA CB CC CD CE DA DB DC DD DE EA EB EC ED EE