Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: Java: Taulukko oliossa ja NullPointerException

Sivun loppuun

JussiR [19.12.2013 18:54:08]

#

Minulla on olio nimeltä tradeData ja jokaisella tälläisellä oliolla pitäisi olla oma taulukko nimeltä ema.
Aina kun yritän asettaa emalle jotain arvoja tai tulostaa sen pituuden, tulee NullPointerException. Jos muutan eman staattiseksi, virheitä ei enää tule, mutta sitten eri olioilla ei ole omaa taulukkoaan...

Mistäköhän johtuisi?

public class tradeData implements Serializable  {

	private static final long serialVersionUID = -3446098372312610589L;
	private int  timestamp;
    private BigInteger  ID;
    private double price ;
    private double [] ema=new double[365]; // array index = ema days
    private double macd;
    private double signal;

	public  tradeData (int timestamp, BigInteger ID, double price) {
		this.timestamp=timestamp;
		this.price=price;
		this.ID=ID;
		this.ema=new double[365];
	}

	public void setema(int days, double emad){
		System.out.println("" + this.ema.length); // <- virhe
		this.ema[days]=emad; // <- virhe
	}

	public void setmacd(){

		this.macd=this.ema[12]-this.ema[26];

	}
}

Metabolix [19.12.2013 19:05:06]

#

Vika on kyllä varmasti jossain muualla, koska esimerkiksi seuraava koodi toimii tuon luokkasi kanssa suoraan:

tradeData tmp = new tradeData(0, null, 0);
tmp.setema(0, 0);
// Tulostaa: 365

Koodissasi luot turhaan kahteen kertaan ema-taulukon. Javassa on myös tapana nimetä luokat isoilla alkukirjaimilla ja muuttujat ja funktiot kamelisti.

JussiR [19.12.2013 19:44:46]

#

En tiedä miten tänne voisi laittaa järkevästi muita osia koodista, kun rivejä on yli 4000 ja tiedostoja 6.

Mulla on tradeData olioita kahdessa eri ArrayListissä.

public class Global {
   	public static List<tradeData> kaikki = new ArrayList<tradeData>();
  	public static List<tradeData> filtered = new ArrayList<tradeData>();
}

Oliot lisätään listaan verkosta haettujen tietojen perusteella.

Toisessa listassa on kaikki tiedot ja toiseen filtteröidään vain osa niistä myöhemmin.

Siihen missä on kaikki, lisätään ne oliot eräässä loopissa tällä tavoin:

Global.kaikki.add(new tradeData(timestamp,ID,priceSum/priceAmount));

Myöhemmin taas eräässä toisessa loopissa käydään koko "kaikki" lista läpi ja if-lauseen avulla lisätään vain osa niistä filtteröityjen listaan.

Global.filtered.add(0,Global.kaikki.get(i)); // lisätään aina listan alkuun

Sitten kun tuo lista on valmis, käydään toisessa loopissa läpi laskutoimituksia, jonka tulokset lisätään listan olion tietoihin:

Global.filtered.get(i).setema(days,avg); // <- NullPointerException setema metodissa

Aluksi mulla oli muutama eri ema muuttuja. double ema12, ema26 jne. Halusin sitten laittaa ne kaikki taulukkoon niiden käsittelyn helpottamiseksi. En ole mielestäni muuttanut mitään muuta, kuin tradeData olion koodia. Tein tuon taulukon ja muutin setema metodia taulukkoa varten ja nyt tulee tuo virhe. Pakko olla jokin tosi yksinkertainen virhe koodissa.

Metabolix [19.12.2013 19:59:39]

#

Etkö nyt voisi edes lukea poikkeuksesta, millä rivillä se oikeasti tulee? Siitä näet, tuleeko se setema-metodissa vai tuossa kutsussa. Jos vielä vähän viitsit yrittää, voit myös if-lauseilla selvittää, mikä kyseisellä rivillä esiintyvistä arvoista on null.

Selityksesi perusteella vaikuttaa melkeinpä ilmeiseltä, että sekoilet joita noiden listojesi kanssa ja siis get(i) palauttaa null-arvon. Varmaan jokin silmukkasi on pielessä.

Siinä epätodennäköisessä tapauksessa, että virhe todella on setema-metodissa, on syytä etsiä ohjelmasta kaikki kohdat, joissa muutat ema-jäsentä (ei siis taulukon sisältöä vaan itse ema-taulukkoviittausta), nimittäin muuttujat eivät muutu itsekseen. Voisi myös olla viisasta merkitä ema finaliksi.

JussiR [19.12.2013 20:27:07]

#

Unohdin mainita, että ihan ohjelman alussa tuo kaikki -lista avataan tiedostosta ObjectInputStreamilla ja sitten vasta lisätään verkosta uusi data. Vika johtuu ilmeisesti siitä, että muutin olion muuttujien tyyppiä ja tiedosto ei ole enää yhteensopiva tämän muuttujan kohdalta.

En tajunnut tuota, koska en aseta emalle arvoja kaikki -listaan ollenkaan ja se on se lista joka tallennetaan/ladataan tiedostosta. Sitten vaan koodaamaan systeemi joka muutaa vanhan datan uuteen muotoon :)

Metabolix [19.12.2013 20:59:14]

#

Luokan serialVersionUID-arvoa pitää vaihtaa, kun muuttaa luokan jäseniä. Se ei tietenkään korjaa virhettäsi vaan ainoastaan helpottaa sen löytämistä.

JussiR [20.12.2013 11:57:38]

#

Joo.

Voiko tuollainen array viedä 25 kertaa enemmän tilaa, kuin pari yksittäistä double muuttujaa, vaikka array on 100% täynnä nullia, koska kaikki -listassa (tämä tallennetaan koneelle) olevissa olioissa en käytä koko ema taulukkoa?

Mulla on tiedostoon tallennettuna 36983 oliota ja nykyinen tiedosto vie 108638 KB tilaa, kun vanha vei vain 4670 KB.

Tallennan ema arrayyn viisi eri arvoa. Ne on EMA-indikaattorin lukuja, mutta eri päivien mukaan laskettuna riippuen tämän softan konffauksesta. Tällä tavalla oli helppo asettaa ja hakea niitä tietoja:

Global.filtered.get(i).setema(Global.customEma,val)

Global.filtered.get(i).getema(Global.customEma)

Global.filtered.get(i).setema(Global.customEma2,val)

Global.filtered.get(i).getema(Global.customEma2)

No niitä on kuitenkin vakiomäärä. Ehkä laitan nille vaan jonkin ID nii taulukko voi olla paljon pienempi (4).

Metabolix [20.12.2013 15:53:54]

#

Taulukossasi ei voi olla null-arvoja, koska alkion tyyppi on double. Taulukossasi on siis nollia. Mikään arvo – ei nolla eikä null – ei tarkoita, etteikö tietoa pitäisi tavalla tai toisella serialisoinnissa tallentaa: onhan sekin tieto, että arvo on nolla tai null. Jos osan muuttujista voisi jättää kokonaan väliin, tiedostosta tulisi taas useissa tilanteissa entistä isompi sen takia, että arvojen lisäksi tarvittaisiin luettelo siitä, mitä muuttujia on tai ei ole tallennettu.

Ei ole järkeä varata taulukkoa, jos haluaa tallentaa vain muutaman arvon. Jos arvoja tarvitaan hyvin pieni vakiomäärä, voisit käyttää erillisiä muuttujia. Toinen vaihtoehto on Map, johon voi tallentaa avaimen ja arvon.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta