Minulla on tehtynä seuraavat luokat, joita yritän testata. Kuitenkin ArrayList luokassa Testiluokka herjaa <identifier> expacted. Missä voisi olla vika?
package vaalisovellus; import java.util.ArrayList; /** * * @author */ public class Testiluokka { //Luodaan 2 kuntaa. Kunta espoo=new Kunta("Espoo",20); Kunta vantaa=new Kunta("Vantaa",60); ArrayList<Kunta> kunnat = new ArrayList<Kunta>(); kunnat.add(espoo);//Herja tulee tältä riviltä. //Luodaan aluksi vaalipiiri. Vaalipiiri uusimaa=new Vaalipiiri("Uusimaa",80,kunnat); }
package vaalisovellus; import java.util.ArrayList; import java.util.HashMap; /** * * @author */ public class Vaalipiiri { private String nimi;//vaalipiirin nimi private int aanioikeutetut; private int annetutAanet; private int hylatytAanet; private int tyhjatAanet; private ArrayList<Kunta> kunnat; private ArrayList<Ehdokas> ehdokkaat; private HashMap<String,ArrayList<Ehdokas>>puolueet; public Vaalipiiri(String nimi,int aanioikeutetut, ArrayList<Kunta> kunnat){ this.nimi=nimi; this.aanioikeutetut=aanioikeutetut; this.kunnat=kunnat; } public Vaalipiiri(String nimi,int aanioikeutetut, ArrayList<Kunta> kunnat, ArrayList<Ehdokas> ehdokkaat){ this.nimi=nimi; this.aanioikeutetut=aanioikeutetut; this.kunnat=kunnat; this.ehdokkaat=ehdokkaat; } public Vaalipiiri(String nimi,int aanioikeutetut, ArrayList<Kunta> kunnat, ArrayList<Ehdokas> ehdokkaat, HashMap<String,ArrayList<Ehdokas>> puolueet){ this.nimi=nimi; this.aanioikeutetut=aanioikeutetut; this.kunnat=kunnat; this.ehdokkaat=ehdokkaat; this.puolueet=puolueet; } public void setAnnetutAanet(int annetutAanet){ this.annetutAanet=annetutAanet; } public void setHylatytAanet(int hylatytAanet){ this.hylatytAanet=hylatytAanet; } public void setTyhjatAanet(int tyhjatAanet){ this.tyhjatAanet=tyhjatAanet; } public void setEhdokkaat(ArrayList<Ehdokas> ehdokkaat){ this.ehdokkaat=ehdokkaat; } public int getAnnetutAanet(){ return annetutAanet; } public String getNimi(){ return nimi; } public int getTyhjatAanet(){ return tyhjatAanet; } public int getHylatytAanet(){ return hylatytAanet; } public ArrayList<Kunta> getKunnat(){ return kunnat; } public ArrayList<Ehdokas> getEhdokkaat(){ return ehdokkaat; } public HashMap<String,ArrayList<Ehdokas>>getPuolueet(){ return puolueet; }
package vaalisovellus; import java.util.ArrayList; import java.util.HashMap; /** * * @author */ public class Kunta { private String nimi; private int aanioikeutetut; private int annetutAanet; private int tyhjatAanet; private int hylatytAanet; private ArrayList<Ehdokas> ehdokkaat; private boolean aakkostettu=false; Kunta(){ } Kunta(String nimi, int aanioikeutetut){ this.nimi=nimi; this.aanioikeutetut=aanioikeutetut; } Kunta(String nimi, int aanioikeutetut, ArrayList<Ehdokas> ehdokkaat){ this.nimi=nimi; this.aanioikeutetut=aanioikeutetut; this.ehdokkaat=ehdokkaat; } public void setAnnetutAanet(int annetutAanet){ this.annetutAanet=annetutAanet; } public void setTyhjatAanet(int tyhjatAanet){ this.tyhjatAanet=tyhjatAanet; } public void setHylatytAanet(int hylatytAanet){ this.hylatytAanet=hylatytAanet; } public void setEhdokkaat(ArrayList<Ehdokas> ehdokkaat){ this.ehdokkaat=ehdokkaat; } public String getNimi(){ return nimi; } public int getAanioikeutetut(){ return aanioikeutetut; } public int getAnnetutAanet(){ return annetutAanet; } public int getTyhjatAanet(){ return tyhjatAanet; } public int getHylatytAanet(){ return hylatytAanet; } public boolean getAakkostettu(){ return aakkostettu; } public ArrayList<Ehdokas> getEhdokkaat(){ return ehdokkaat; }
Vika on siinä, että et voi tehdä muuta kuin määritellä luokan jäsenmuuttujia (ja luokkia) funktioiden ulkopuolella. Nuo alustustoiminnot kuuluisivat todennäköisesti konstruktoriin:
package vaalisovellus; import java.util.ArrayList; /** * * @author */ public class Testiluokka { //Luodaan 2 kuntaa. Kunta espoo; Kunta vantaa; ArrayList<Kunta> kunnat; Vaalipiiri uusimaa; public Testiluokka() { this.espoo = new Kunta("Espoo", 20); //Luodaan aluksi vaalipiiri. this.vantaa = new Kunta("Vantaa", 60); this.kunnat = new ArrayList<>(); this.kunnat.add(espoo); this.uusimaa = new Vaalipiiri("Uusimaa", 80, this.kunnat); } }
Koodia kannattaa ehkä jakaa hieman järkevämpiin osiin, mutta ainakin tuolla koodilla sinun pitäisi päästä alkuun.
OK. Kiitos tästä.
Niin tai jotta edes pystyt suorittaa tuota ohjelmaa, niin sinun olisi hyvä tehdä Testiluokkaan main-metodi ja kirjoittaa tuo testikoodi sinne.
En kyllä tajua, mikä järki tuollaisessa nimettyjen kuntien tunkemisessa jäsenmuuttujiin on. Tee ennemmin yksi muuttuja, joka on map-säiliö, johon voit pistää kuntia nimettyihin indekseihin.
this.cities = new Map<string, City>(); this.cities["espoo"] = new City("Espoo"); this.cities["vantaa"] = new City("Vantaa");
Koodi on pseudoa, miten lie javalla tehtäisiinkään.
Mulla on nyt tämän saman homman kanssa toinen ongelma:
Olen tehnyt pääluokkaan olion, jolla testaan eli pääluokka näyttää tältä:
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package vaalisovellus; /** * * @author */ public class Vaalisovellus { /** * @param args the command line arguments */ public static void main(String[] args) { // TODO code application logic here Testiluokka testiolio=new Testiluokka(); testiolio.Testi(); } }
Ja testiluokka on puolestaan tällainen:
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package vaalisovellus; import java.util.ArrayList; /** * * @author */ public class Testiluokka { //Luodaan 2 kuntaa. Kunta espoo=new Kunta("Espoo",20); Kunta vantaa=new Kunta("Vantaa",60); ArrayList<Kunta> kunnat = new ArrayList<Kunta>(); ArrayList<Ehdokas>puolueEhdokkaat=new ArrayList<Ehdokas>(); ArrayList<Puolue>puolueet=new ArrayList<Puolue>(); ArrayList<Ehdokas>apuEhdokkaat=new ArrayList<Ehdokas>(); //Luodaan aluksi vaalipiiri. public void Testi(){ kunnat.add(espoo); kunnat.add(vantaa); puolueet.add(new Puolue("kokoomus")); puolueet.add(new Puolue("kristilliset")); puolueet.add(new Puolue("persut")); Vaalipiiri uusimaa=new Vaalipiiri("Uusimaa",80,kunnat); for(int i=0;i<5;i++){ puolueEhdokkaat.add(new Ehdokas("K"+i,"kok","uusimaa",i)); apuEhdokkaat.add(puolueEhdokkaat.get(i)); System.out.println("Lisätty ehdokas "+puolueEhdokkaat.get(i).getNimi()+" puolueesta "+puolueEhdokkaat.get(i).getPuolue()+"."); } System.out.println(apuEhdokkaat.size()); puolueet.get(0).setEhdokkaat(apuEhdokkaat); apuEhdokkaat.clear(); for(int i=5;i<10;i++){ puolueEhdokkaat.add(new Ehdokas("R"+i,"kd","uusimaa",i)); apuEhdokkaat.add(puolueEhdokkaat.get(i)); System.out.println("Lisätty ehdokas "+puolueEhdokkaat.get(i).getNimi()+" puolueesta "+puolueEhdokkaat.get(i).getPuolue()+"."); } puolueet.get(1).setEhdokkaat(apuEhdokkaat); System.out.println(""+puolueet.get(1).getEhdokkaat().size()); apuEhdokkaat.clear(); for(int i=10;i<15;i++){ puolueEhdokkaat.add(new Ehdokas("P"+i,"ps","uusimaa",i)); apuEhdokkaat.add(puolueEhdokkaat.get(i)); System.out.println("Lisätty ehdokas "+puolueEhdokkaat.get(i).getNimi()+" puolueesta "+puolueEhdokkaat.get(i).getPuolue()+"."); } puolueet.get(2).setEhdokkaat(apuEhdokkaat); System.out.println(""+puolueet.get(2).getEhdokkaat().size()); apuEhdokkaat.clear(); for(int i=0;i<puolueet.size();i++){ System.out.println("Puolue: "+puolueet.get(i).getNimi()); System.out.println(puolueet.get(i).getEhdokkaat().size()); apuEhdokkaat=puolueet.get(i).getEhdokkaat(); System.out.println(""+apuEhdokkaat.size()); for(int j=0;j<apuEhdokkaat.size();j++){//EI MENE KOSKAAN TÄNNE! System.out.println("Ehdokkaat:"+apuEhdokkaat.get(j).getNimi()); } } } }
Se ei koskaan testatessa mene tuohon viimeiseen for-looppiin. Tiedän, että se johtuu siitä, että apuEhokkaat ArrayListin pituus on nolla, mutta en ymmärrä, mitä väärää olen tehnyt, koska tuolla aiemmin apuehokkaisiin on laitettu tavaraa ja ne on vielä sijoitettu sinne puolueeseen.
Tulostus, joka tulee on seuraava:
isätty ehdokas K0 puolueesta kok.
Lisätty ehdokas K1 puolueesta kok.
Lisätty ehdokas K2 puolueesta kok.
Lisätty ehdokas K3 puolueesta kok.
Lisätty ehdokas K4 puolueesta kok.
5
Lisätty ehdokas R5 puolueesta kd.
Lisätty ehdokas R6 puolueesta kd.
Lisätty ehdokas R7 puolueesta kd.
Lisätty ehdokas R8 puolueesta kd.
Lisätty ehdokas R9 puolueesta kd.
5
Lisätty ehdokas P10 puolueesta ps.
Lisätty ehdokas P11 puolueesta ps.
Lisätty ehdokas P12 puolueesta ps.
Lisätty ehdokas P13 puolueesta ps.
Lisätty ehdokas P14 puolueesta ps.
5
Puolue: kokoomus
0
0
Puolue: kristilliset
0
0
Puolue: persut
0
0
Koodissa ei pitäisi olla noita clear-kutsuja. Niissä tyhjennät ehdokaslistan. Jos haluat vain, että muuttuja apuEhdokkaat ei enää osoita tiettyyn puolueeseen (tai ylipäänsä mihinkään), sijoita siihen arvo null.
Testasin tuota. Nyt tuli nullpointer Exception eli tällainen virheilmoitus:
Lisätty ehdokas K0 puolueesta kok.
Exception in thread "main" java.lang.NullPointerException
Lisätty ehdokas K1 puolueesta kok.
Lisätty ehdokas K2 puolueesta kok.
Lisätty ehdokas K3 puolueesta kok.
Lisätty ehdokas K4 puolueesta kok.
5
at vaalisovellus.Testiluokka.Testiluominen(Testiluokka.java:38)
at vaalisovellus.Vaalisovellus.main(Vaalisovellus.
Java Result: 1
muutos, jonka tein oli, että kirjoitin rivin
apuEhdokkaat.clear();
tilalle
apuEhdokkaat=null;
Lisäys:
Kokeilin myös tekemällä seuraavan metodin:
private static void tyhjenna(ArrayList tyhjennettava){ while(!tyhjennettava.isEmpty()){ for(int i=0;i<tyhjennettava.size();i++){ tyhjennettava.remove(i); } }
ja kutsumalla tätä tuon apuEhdokkaat=null; tilalla seuraavasti:
tyhjenna(apuEhdokkaat);
Siitä huolimatta alkuperäinen ongelma ei ratkennut.
Luin koodiasi äsken huolimattomasti. Varsinainen ongelma on, että käytät jokaiselle puolueelle samaa ehdokaslistaa. Sinun pitäisi siis ennen kohtaa setEhdokkaat(apuEhdokkaat) luoda oikeasti aina uusi lista. Äsken mainitsemaani null-sijoitusta ei kuulu tehdä, mutta myöskään clear-rivejä ei silti kuulu olla, koska uusi lista on jo valmiiksi tyhjä.
Tästä opittava asia on, että Javassa muuttuja ei sisällä kokonaista oliota vaan vain viittauksen olioon. Olioita on tasan sen verran, kuin new-operaattorilla luodaan; sijoituksessa vain liitetään sama olio uuteen muuttujaan.
eli tarvitsen siis jokaiselle puolueelle oman apuEhdokkaat-listan? Eli yksi tuollainen lista on ikäänkuin "kertakäyttöinen" eli mun pitää tehdä apuEhdokkaatKok, apuEhdokkaatKd ja apuEhdokkaatPs erikseen?
Lisäys:
Muutin tuon koko lohkon seuraavaksi, mutta edelleen sama ongelma:
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package vaalisovellus; import java.util.ArrayList; /** * * @author */ public class Testiluokka { //Luodaan 2 kuntaa. Kunta espoo=new Kunta("Espoo",20); Kunta vantaa=new Kunta("Vantaa",60); ArrayList<Kunta> kunnat = new ArrayList<Kunta>(); ArrayList<Ehdokas>puolueEhdokkaat=new ArrayList<Ehdokas>(); ArrayList<Puolue>puolueet=new ArrayList<Puolue>(); ArrayList<Ehdokas>apuEhdokkaatKok=new ArrayList<Ehdokas>(); ArrayList<Ehdokas>apuEhdokkaatKd=new ArrayList<Ehdokas>(); ArrayList<Ehdokas>apuEhdokkaatPs=new ArrayList<Ehdokas>(); //Luodaan aluksi vaalipiiri. public void Testiluominen(){ kunnat.add(espoo); kunnat.add(vantaa); puolueet.add(new Puolue("kokoomus")); puolueet.add(new Puolue("kristilliset")); puolueet.add(new Puolue("persut")); Vaalipiiri uusimaa=new Vaalipiiri("Uusimaa",80,kunnat); for(int i=0;i<5;i++){ puolueEhdokkaat.add(new Ehdokas("K"+i,"kok","uusimaa",i)); apuEhdokkaatKok.add(puolueEhdokkaat.get(i)); System.out.println("Lisätty ehdokas "+puolueEhdokkaat.get(i).getNimi()+" puolueesta "+puolueEhdokkaat.get(i).getPuolue()+"."); } System.out.println(apuEhdokkaatKok.size()); puolueet.get(0).setEhdokkaat(apuEhdokkaatKok); tyhjenna(apuEhdokkaatKok); for(int i=5;i<10;i++){ puolueEhdokkaat.add(new Ehdokas("R"+i,"kd","uusimaa",i)); apuEhdokkaatKd.add(puolueEhdokkaat.get(i)); System.out.println("Lisätty ehdokas "+puolueEhdokkaat.get(i).getNimi()+" puolueesta "+puolueEhdokkaat.get(i).getPuolue()+"."); } puolueet.get(1).setEhdokkaat(apuEhdokkaatKd); System.out.println(""+puolueet.get(1).getEhdokkaat().size()); tyhjenna(apuEhdokkaatKd); for(int i=10;i<15;i++){ puolueEhdokkaat.add(new Ehdokas("P"+i,"ps","uusimaa",i)); apuEhdokkaatPs.add(puolueEhdokkaat.get(i)); System.out.println("Lisätty ehdokas "+puolueEhdokkaat.get(i).getNimi()+" puolueesta "+puolueEhdokkaat.get(i).getPuolue()+"."); } puolueet.get(2).setEhdokkaat(apuEhdokkaatPs); System.out.println(""+puolueet.get(2).getEhdokkaat().size()); tyhjenna(apuEhdokkaatPs); } public void testiTulostus(){ for(int i=0;i<puolueet.size();i++){ System.out.println("Puolue: "+puolueet.get(i).getNimi()); System.out.println(puolueet.get(i).getEhdokkaat().size());//TÄSTÄ TULOSTUU AINA NOLLA apuEhdokkaatKok=puolueet.get(i).getEhdokkaat(); System.out.println(""+apuEhdokkaatKok.size()); for(int j=0;j<apuEhdokkaatKok.size();j++){//EI MENE KOSKAAN TÄNNE! System.out.println("Ehdokkaat:"+apuEhdokkaatKok.get(j).getNimi()); } } } private static void tyhjenna(ArrayList tyhjennettava){ while(!tyhjennettava.isEmpty()){ for(int i=0;i<tyhjennettava.size();i++){ tyhjennettava.remove(i); } } } }
LCHawk kirjoitti:
Eli yksi tuollainen lista on ikäänkuin "kertakäyttöinen" eli mun pitää tehdä apuEhdokkaatKok, apuEhdokkaatKd ja apuEhdokkaatPs erikseen?
EI! Sanoin juuri, että sinun pitää aina luoda new-operaattorilla uusi lista. Voit ihan hyvin käyttää sille samaa muuttujaa. Listaa ei vain pidä koskaan tyhjentää.
Yritänpä selittää konkreettisesti, mitä aiempi koodisi tekee. Alussa (new-kohdassa) otat uuden paperin ja merkkaat yläkulmaan, että tämä on nyt lomake L1. Kirjoitat paperiin ehdokkaat K0-K4 ja ilmoitat puolueelle X, että lomake L1 on heidän vaalilistansa. Sitten kumitat ehdokkaat lomakkeelta (clear, tyhjenna) ja käytät sen samalla tavalla toisen ja vielä kolmannenkin puolueen listana. Kun lopussa puolue X tulee pyytämään sinulta lomaketta L1, siinä ei tietenkään ole enää heidän listaansa, koska olet pyyhkinyt sen pois; lomakkeella on vain kolme sutattua ehdokaslistaa.
Uudessa koodissasi pyyhit paperin samalla tavalla, mutta sitten otatkin seuraavalle puolueelle uuden paperin, jonka myös lopuksi pyyhit. Tuloksena on kolme tyhjää paperia, joka puolueella oma.
Sinun pitäisi antaa joka puolueelle oma paperi eli luoda jokaiselle uusi lista (new ArrayList). On ihan sama, missä muuttujassa sitä pidät; muuttuja on samanlainen väliaikainen määre kuin arkielämässä ”tämä paperi kädessäni”, eli voit antaa ensimmäisen paperin puolueelle ja ottaa sitten käteen uuden paperin.
Toisena asiana tahdon huomauttaa, että on aika sekavaa ensin laittaa puolueet listalle ja sitten hakea niitä numeron perusteella: mitä käy, jos haluat lisätä väliin uuden puolueen? Sen sijaan kannattaa suosia paikallisia apumuuttujia. Apumuuttujat eivät missään nimessä kuulu tuonne luokan muuttujien joukkoon.
Puolue puolue; ArrayList<Ehdokas> lista; puolue = new Puolue("X:n kannattajain liitto", "X"); lista = new ArrayList<Ehdokas>(); for (int i = 0; i < 5; ++i) { String nimi = puolue.getTunnus() + i; Ehdokas ehdokas = new Ehdokas(nimi, puolue); lista.add(ehdokas); System.out.println(ehdokas.getNimi() + " kuuluu puolueeseen " + ehdokas.getPuolue().getNimi() + "."); } puolue.setLista(lista); puolueet.add(puolue); puolue = new Puolue("Y:n ylistäjäin yhdistys", "Y"); lista = new ArrayList<Ehdokas>(); // ...
OK. Nyt tämä homma toimii, kiitos hirvittävästi.
Tuon koko ohjelman (jonka tekoa vasta aloittelen) ideana olisi simuloida eduskuntavaaleja yhden vaalipiirin osalta eli sen pitäisi lukea tekstitiedostoja, joissa olisi aina puolueen nimi ja ko. puolueen ehdokkaat. Sen pitäisi tämän jälkeen lukea lisää tekstiedostoja, joissa olisi aina jokaiselta kunnalta kaikkia annetut äänet ja laskea näiden perusteella tulokset ja sitten kirjoittaa tekstitiedosto, jossa on kerrottu eli puoluiden läpimenneet ehdokkaat.
Aihe on jo aika vanha, joten et voi enää vastata siihen.