Koodini näyttää tältä:
try { while (tarkista()) { //tässä tehdään jotain } } catch (Exception e) {}
Kysymys kuuluukin mitä tapahtuu jos while-silmukassa tapahtuu virhe ja tuo try...catch rakenne nappaa sen virheen? Jääkö while-silmukka pyörimään kunnes itse sen jollain tavalla lopetan? Ja jos ei, onko mitään keinoa saada se jäämään pyörimään?
Ei jää pyörimään, mutta näin jäisi:
while (tarkista()) { try { // tässä tehdään jotain } catch (Exception e) {} }
Mutta mitäs sitten jos tuo tarkista()-metodikin voi heittää virhettä? Jos se aiheuttaa virheen niin sehän jää nyt käsittelemättä jos oikein ymmärsin?
Miten koodin pitäisi käyttäytyä, jos tarkista() heittää virheen? Jatkaa whilen pyörittämistä?
Muoks: Jos kyllä, niin tässä yksi keino näillä puutteellisilla tiedoilla:
while (true) { try { if (!tarkista()) { break; } // tässä tehdään jotain } catch (Exception e) {} }
Kyllä eli while-silmukan pitäisi pyöriä niin kauan kunnes tarkista()-metodi palauttaa falsen ja virhe ei saisi häiritä tätä while-silmukan pyörimistä.
Antamani koodi ei pyöritä while-silmukan muuta sisältöä, jos tarkista() heittää virhettä, mutta osaat varmasti muokata sitä itse tarpeen mukaan.
Nähdäkseni koodisi ei ole oikein suunniteltu, koska tuossa osassa ollessaa try...catch rakenne tutkii juurikin while silmukan heittämiä virheitä. Tuossahan heitetty virhe on juurikin niin fataali, että silmukan jatko ei ole mielekästä. Esimerkiksi välitulokseen tulisi nollalla jako tai vastaavaa.
Silmukan jatkaminen olisi mahdolisesti toteutettavissa continue käskyllä, jolloin silmukan loppu jätetään käsittelemättä, mutta aloitetaan kuitenkin uusi kierros. Virheiden heittämisen tarkoitus ei ole virheiden kiertäminen, vaan niistä toipuminen. Virhe tulisikin kaiketi heittää juurikin silloin, kun jatkaminen ei ole mielekästä.
Tumettaja kirjoitti:
Kyllä eli while-silmukan pitäisi pyöriä niin kauan kunnes tarkista()-metodi palauttaa falsen ja virhe ei saisi häiritä tätä while-silmukan pyörimistä.
Mitäs himpskattia? Eli, kun tulee virhe sen pitäisi pysähtyä, mutta ei sittenkään saisi pysähtyä?
"while-silmukan pitäisi pyöriä niin kauan kunnes tarkista()-metodi palauttaa falsen"
Eli virheen tullessa lopetettaisiin käsittely.
"ja virhe ei saisi häiritä tätä while-silmukan pyörimistä"
Eli virheestä huolimatta jatkettaisiin.
Kumman nyt haluat?
while(true) { if(!tarkista()) { // tarkista() palautti falsen, lopetetaan koko silmukka break; } // Muutoin jatketaan pyörimistä... }
while(true) { if(!tarkista()) { // tarkista() palautti falsen, lopetetaan tämä kierros continue; } // Muutoin jatketaan pyörimistä... }
Macro, virheellä viitattiin siihen kolmanteen vaihtoehtoon, jossa funktio ei palauta mitään vaan suoritus hyppää catch-lohkoon.
Jos oikeasti olet sitä mieltä, että tarkistuksessa tapahtuva virhe ei saa keskeyttää silmukkaa, selkein ratkaisu olisi tehdä erillinen funktio, joka käsittelisi tarkista-funktion poikkeuksen ja palauttaisi sen lopullisen päätöksen.
boolean tarkista_oikeasti() { while (true) { try { return tarkista(); } catch (Exception e) { // Virhe; silmukka jatkuu, tarkistetaan uudestaan. // Voitaisiin myös palauttaa suoraan true tai false. } } } // Oikea silmukka; tarkista_oikeasti ei heitä poikkeusta. // Lisää try-lohko haluamaasi paikkaan. while (tarkista_oikeasti()) { // ... }
Mutta, jollei funktio palauta mitään, niin if-lauseessa se käsitellään falsena.
Macro kirjoitti:
Mutta, jollei funktio palauta mitään, niin if-lauseessa se käsitellään falsena.
Väärin. Poikkeus keskeyttää funktion suorituksen ennen kuin siitä poistutaan normaalisti. Tällöin kyseinen funktio ei palauta mitään, eikä if-lauseen sisältöä selvitetä, vaan suoritus hyppää sopivaan catch-lohkoon (tai jos sellaista ei löydy miltään tasolta, ohjelman suoritus päättyy).
Muoks: Sekoitatkohan Pythoniin, jossa return-lauseen puuttuminen vastaa samaa kuin return None? Silti poikkeukset käyttäytyvät samoin siinäkin, eli suoritus hyppää aivan eri kohtaan, eikä funktiosta poistuta niin että sen paluuarvoa tulkittaisiin millään tavalla.
Macro kirjoitti:
Mutta, jollei funktio palauta mitään, niin if-lauseessa se käsitellään falsena.
Javassa ei edes ole mahdollista tehdä funktiota, joka ei palauttaisi sitä, mitä sen etukäteen on ilmoitettu palauttavan (tässä true tai false). Kääntäjä tarkistaa, että funktiosta löytyy joka tilanteessa return-lause (tai throw-rivi, jos nyt sille linjalle lähdetään; Chiman tästä jo selittikin).
Varmaan ajattelet nyt PHP:tä tai muita skriptikieliä, joissa "ei mitään" tarkoittaa yleensä samaa kuin null- tai None-arvon palauttaminen. Sen sijaan vaikkapa C:ssä return-lauseen puuttumisesta seuraa, että funktion paluuarvoksi tulee suhteellisen satunnainen arvo tietokoneen muistista.
Juu, en ole koskaan Javaa ohjelmoinut, niin ajattelin sen käyttäytyvän kuten Python ja PHP.
Jos tarkista-metodissa tapahtuu virhetilanteita, joista pystytään selviämään, on oikea paikka käsitellä nämä virheet tuon metodin sisällä. On hyvin kyseenalaista, että tällainen tarkistus-metodi heittää ulos mitään hallittavia virheitä. Kriittiset RuntimeException ovat asia erikseen ja niitä ei todennäköisesti kannattaisi hallita tällä tasolla.
boolean tarkista() { try { //Normaali tarkistuskoodi //return true/false ... } catch (IOException e) { //Hallittu virhe, pahaksi havaittu virhetilanne, silmukka ei jatku return false; } catch (Exception e) { //Hallittu virhe, tuntematon virhetilanne, sormet ristiin, silmukka jatkuu return true; } }
Taas kerran kannattaisi näyttää ihan oikea konkreettinen koodi, jotta saa oikeita vastauksia. Jos ei osaa ratkaista ongelmaa, osaa harvoin myöskään esittää algoritmia karsittuna niin, että kaikka asiaan vaikuttavat tekijät siinä edelleen näkyvät. Tumettaja ehkä vaan yrittää tehdä jotain, mitä ei pitäisi lainkaan tehdä, tai sitten ongelmaan on helppo ratkaisu. Anna Tumettaja todellinen koodi, niin saat neuvoja kuinka se kannattaa toteuttaa.
Yleisesti ottaenhan metodi aina kirjoitetaan niin, ettei virhettä voi tapahtua, siis tarkastetaan parametrit. Sitten on tilanteita, kuten vaikkapa tietokantaoperaatiot, joissa voi tapahtua virhe. Silloin päätetään kuinka toimitaan, jos virhe tapahtuu, usein se on fataali, eli voidaan yrittää joku kerta uudestaan, mutta jos ei sittenkään onnistu, niin hyväksytään tilanne. Yleensä ko. tapauksessa jo yksi epäonnistuminen aiheuttaa ohjelman keskeytyksen, mutta on toki ongelmia, jotka poistuvat ajan myötä, ja sitten voidaan jatkaa. Tuskin koskaan voidaan jäädä loputtomiin yrittämään, että jos nyt homma toimisi.
Aihe on jo aika vanha, joten et voi enää vastata siihen.