package dynaaminen; import java.lang.reflect.InvocationTargetException; /** * Esimerkki dynaamisesta taulukosta Java 1.5:n geneerisyytt� * ja reflektiona k�ytt�en niin, ett� voi tallentaa vain * alkiota jotka toteuttavat tietyn rajapinnan ja uusi * alkio luodaan lis�yksen yhteydess�. * @author Vesa Lappalainen * @version 1.0, 02.03.2002 * @version 1.1, 01.03.2005 */ interface LukuRajapinta { public void set(int i); public int get(); } class Luku implements LukuRajapinta { int luku; public Luku() {} public Luku(int i) { luku = i; } @Override public int get() { return luku; } @Override public void set(int i) { luku = i; } @Override public String toString() { return "" + luku; } } /** * Esimerkki rajoitetusta luokasta * @param <TYPE> luokan yleinen tyyppi joka pit�� olla LukuRajapintaa */ public class TaulukkoGenExt<TYPE extends LukuRajapinta> { /** Luokka t�yden taulukon poikkeusta varten */ public static class TaulukkoTaysiException extends Exception { private static final long serialVersionUID = 1L; TaulukkoTaysiException(String viesti) { super(viesti); } } private Class<TYPE> luokka; // = TYPE.class; Tyhm��, n�in ei voi sanoa... private TYPE alkiot[]; private int lkm; /** * @param luokka mit� tallennetaan */ public TaulukkoGenExt(Class<TYPE> luokka) { this(luokka, 10); } /** * @param luokka mit� tallennetaan * @param koko taulukon aloituskoko */ @SuppressWarnings("unchecked") public TaulukkoGenExt(Class<TYPE> luokka, int koko) { alkiot = (TYPE[]) new Object[koko]; this.luokka = luokka; } /** * @param luku mik� alkio lis�t��n * @throws TaulukkoTaysiException jos taulukkoon ei mahdu */ public void lisaa(int luku) throws TaulukkoTaysiException { try { TYPE uusi; uusi = luokka.getConstructor().newInstance(); uusi.set(luku); if (lkm >= alkiot.length) throw new TaulukkoTaysiException("Tila loppu"); alkiot[lkm++] = uusi; } catch (IllegalAccessException ex) { throw new TaulukkoTaysiException("Laiton viittaus " + ex.getMessage()); } catch (InstantiationException ex) { throw new TaulukkoTaysiException("Laiton uuden luonti " + ex.getMessage()); } catch (IllegalArgumentException ex) { throw new TaulukkoTaysiException("Laiton argumentti " + ex.getMessage()); } catch (InvocationTargetException ex) { throw new TaulukkoTaysiException("Laiton kohde " + ex.getMessage()); } catch (NoSuchMethodException ex) { throw new TaulukkoTaysiException("Ei metodia " + ex.getMessage()); } catch (SecurityException ex) { throw new TaulukkoTaysiException("Suojausvirhe " + ex.getMessage()); } } @Override public String toString() { StringBuilder s = new StringBuilder(""); for (int i = 0; i < lkm; i++) s.append(" " + alkiot[i]); return s.toString(); } /** * @param i mihin paikkaan laitetaan * @param luku mik� arvo laitetaan * @throws IndexOutOfBoundsException jos huono indeksi */ public void set(int i, int luku) throws IndexOutOfBoundsException { if ((i < 0) || (lkm <= i)) throw new IndexOutOfBoundsException("i = " + i); alkiot[i].set(luku); } /** * @param i mist� paikasta haetaan * @return paikassa i oleva arvo * @throws IndexOutOfBoundsException jos huono indeksi */ public int get(int i) throws IndexOutOfBoundsException { if ((i < 0) || (lkm <= i)) throw new IndexOutOfBoundsException("i = " + i); return alkiot[i].get(); } /** * Testataan taulukkoa * @param args ei k�yt�ss� */ public static void main(String[] args) { TaulukkoGenExt<Luku> luvut = new TaulukkoGenExt<Luku>(Luku.class); try { luvut.lisaa(0); luvut.lisaa(2); luvut.lisaa(99); // Tekee oikeasti luvut.lisaa(new Integer(99)); } catch (TaulukkoTaysiException e) { System.out.println("Virhe: " + e.getMessage()); } System.out.println(luvut); luvut.set(1, 4); System.out.println(luvut); int luku = luvut.get(2); // oik: luku = luvut.get(2).intValue(); System.out.println("Paikassa 2 on " + luku); try { luvut.set(21, 4); } catch (IndexOutOfBoundsException e) { System.out.println("Virhe: " + e.getMessage()); } } }