Ohjelmointi

Kuinka käyttää väitteitä Java

Suoritusaikana oikein toimivien ohjelmien kirjoittaminen voi olla haastavaa. Tämä johtuu siitä, että oletuksemme siitä, miten koodimme käyttäytyy suoritettaessa, ovat usein väärät. Java-väiteominaisuuden käyttäminen on yksi tapa varmistaa, että ohjelmointilogiikkasi on moitteeton.

Tämä opetusohjelma esittelee Java-väitteet. Opit ensin, mitkä väitteet ovat, ja kuinka määritellä ja käyttää niitä koodissasi. Seuraavaksi opit, kuinka väitteiden avulla voidaan panna täytäntöön ennakko- ja jälkiehtoja. Lopuksi verrataan väitteitä poikkeuksiin ja saat selville, miksi tarvitset molempia koodissasi.

lataa Hanki koodi Lataa lähdekoodi esimerkkejä tästä opetusohjelmasta. Luonut Jeff Friesen JavaWorldille.

Mitä Java-väitteet ovat?

Ennen JDK 1.4: ta kehittäjät käyttivät usein kommentteja dokumentoidakseen oletuksia ohjelman oikeellisuudesta. Kommentit ovat kuitenkin hyödyttömiä oletusten testaamisen ja virheenkorjauksen mekanismina. Kääntäjä jättää kommentit huomiotta, joten niitä ei voida mitenkään käyttää virheen havaitsemiseen. Kehittäjät eivät myöskään päivitä kommentteja usein koodia vaihdettaessa.

JDK 1.4: ssa väitteet otettiin käyttöön uutena mekanismina koodia koskevien oletusten testaamiseksi ja virheenkorjaamiseksi. Pohjimmiltaan väitteitä ovat käännettäviä kokonaisuuksia, jotka suoritetaan ajon aikana olettaen, että olet ottanut heidät käyttöön ohjelmatestauksessa. Voit ohjelmoida väitteitä ilmoittamaan virheistä, joissa virheitä esiintyy, mikä vähentää huomattavasti aikaa, jonka muuten vietät viallisen ohjelman virheenkorjaukseen.

Väitteitä käytetään koodaamaan vaatimukset, jotka tekevät ohjelmasta oikean tai ei testaamalla olosuhteissa (Boolen lausekkeet) oikeille arvoille ja ilmoittaminen kehittäjälle, kun tällaiset ehdot ovat vääriä. Väitteiden käyttö voi lisätä luottamustasi koodisi oikeellisuuteen.

Kuinka kirjoittaa väite Java-kielellä

Väitteet toteutetaan väittävät lausunto ja java.lang.AssertionError luokassa. Tämä lause alkaa avainsanalla väittävät ja jatkaa Boolen lausekkeella. Se ilmaistaan ​​syntaktisesti seuraavasti:

väittävät TotuusarvoLauseke;

Jos TotuusarvoLauseke arvioi arvon tosi, mitään ei tapahdu ja toteutus jatkuu. Jos lauseke arvioidaan vääräksi, VäiteVirhe on instantisoitu ja heitetty, kuten luettelo 1 osoittaa.

Listaus 1:AssertDemo.java (versio 1)

julkinen luokka AssertDemo {public static void main (String [] args) {int x = -1; väitä x> = 0; }}

Listauksen 1 väite osoittaa kehittäjän uskovan muuttujaan x sisältää arvon, joka on suurempi tai yhtä suuri kuin 0. Tämä ei kuitenkaan selvästikään ole asia; väittävät lauseen toteutus johtaa heittoon VäiteVirhe.

Koosta luettelo 1 (javac AssertDemo.java) ja suorita se sallittujen väitteiden kanssa (java -ea AssertDemo). Ota huomioon seuraava tulos:

Poikkeus säikeessä "main" java.lang.AssertionError at AssertDemo.main (AssertDemo.java:6)

Tämä viesti on jonkin verran salaperäinen, koska siinä ei tunnisteta, mikä aiheutti viestin VäiteVirhe heittää. Jos haluat informatiivisemman viestin, käytä väittävät alla esitetty lausunto:

väittävät TotuusarvoLauseke : lauseke;

Tässä, lauseke on mikä tahansa lauseke (mukaan lukien menetelmän kutsu), joka voi palauttaa arvon - et voi kutsua menetelmää a: lla mitätön palautustyyppi. Hyödyllinen lauseke on merkkijonolitraali, joka kuvaa epäonnistumisen syytä, kuten luettelossa 2 on esitetty.

Listaus 2:AssertDemo.java (versio 2)

julkinen luokka AssertDemo {public static void main (String [] args) {int x = -1; väitä x> = 0: "x <0"; }}

Koosta luettelo 2 (javac AssertDemo.java) ja suorita se sallittujen väitteiden kanssa (java -ea AssertDemo). Tällä kertaa sinun tulee tarkkailla seuraavaa hieman laajennettua lähtöä, joka sisältää syyn heitolle VäiteVirhe:

Poikkeus säikeessä "main" java.lang.AssertionError: x <0 at AssertDemo.main (AssertDemo.java:6)

Kummassakin esimerkissä juoksu AssertDemo ilman -ja (Ota väitteet käyttöön) -vaihtoehto ei tuota tulosta. Kun väitteet eivät ole käytössä, niitä ei suoriteta, vaikka ne ovat edelleen luokkatiedostossa.

Edellytykset ja jälkisehdot

Väitteet testaavat ohjelman oletuksia varmistamalla, että sen eri edellytyksiä ja jälkiehtoja ei rikota, ja ilmoittavat kehittäjälle rikkomuksen tapahtuessa:

  • A edellytys on ehto, jonka on arvioitava tosi ennen jonkin koodisekvenssin suorittamista. Edellytykset takaavat, että soittajat pitävät sopimuksensa Calleesin kanssa.
  • A jälkikäsittely on ehto, jonka on arvioitava tosi jonkin koodisekvenssin suorittamisen jälkeen. Jälkisehdot varmistavat, että henkilöt pitävät sopimukset soittajien kanssa.

Edellytykset

Voit valvoa julkisten rakentajien ja menetelmien edellytyksiä tekemällä tarkat tarkastukset ja tarvittaessa tekemällä poikkeuksia. Yksityisillä auttajamenetelmillä voit pakottaa ennakkoehtoja määrittämällä väitteet. Harkitse listaa 3.

Listaus 3:AssertDemo.java (versio 3)

tuo java.io.FileInputStream; tuo java.io.InputStream; tuo java.io.IOException; luokka PNG {/ ** * Luo PNG-ilmentymä, lue määritetty PNG-tiedosto ja dekoodaa * se sopiviksi rakenteiksi. * * @param filespec -polku ja luettavan PNG-tiedoston nimi * * @throws NullPointerException kun tiedostomuoto On * tyhjä * / PNG (String filepec) heittää IOException {// Pakota ennakkoedellytykset muille kuin yksityisille rakentajille ja // -menetelmille. if (filespec == null) heittää uusi NullPointerException ("tiedostotyyppi on tyhjä"); kokeile (FileInputStream fis = new FileInputStream (filespec)) {readHeader (fis); }} private void readHeader (InputStream is) heittää IOException {// Vahvista, että ennakkoehto täyttyy yksityisissä // auttajametodeissa. assert is! = null: "null siirretty on"; }} public class AssertDemo {public static void main (String [] args) heittää IOException {PNG png = uusi PNG ((args.pituus == 0)? null: args [0]); }}

PNG luokka 3 on pienin kirjaston alku PNG-kuvatiedostojen (kannettava verkkografiikka) lukemiseen ja dekoodaamiseen. Rakentaja vertaa nimenomaisesti tiedostomuoto kanssa tyhjä, heittää NullPointerException kun tämä parametri sisältää tyhjä. Tarkoituksena on valvoa sitä tiedostomuoto eivät sisällä tyhjä.

Ei ole asianmukaista määritellä assert filespec! = null; koska rakentajan Javadocissa mainittua edellytystä ei (teknisesti) kunnioiteta, kun väitteet poistetaan käytöstä. (Itse asiassa se olisi kunnia, koska FileInputStream () heittäisi NullPointerException, mutta sinun ei pitäisi olla riippuvainen dokumentoimattomasta käytöstä.)

Kuitenkin, väittävät on sopiva yksityisen yhteydessä readHeader () helper-menetelmä, joka valmistuu lopulta PNG-tiedoston 8-tavuisen otsikon lukemiseen ja dekoodaamiseen. Edellytys sille On aina välitetään, ei-nolla-arvo pysyy aina voimassa.

Jälkisehdot

Jälkisehdot määritellään tyypillisesti väitteiden avulla riippumatta siitä, onko menetelmä (tai rakentaja) julkinen vai ei. Harkitse listaa 4.

Listaus 4:AssertDemo.java (versio 4)

public class AssertDemo {public static void main (String [] args) {int [] array = {20, 91, -6, 16, 0, 7, 51, 42, 3, 1}; lajittelu (taulukko); for (int element: array) System.out.printf ("% d", elementti); System.out.println (); } yksityinen staattinen looginen arvo onSorted (int [] x) {for (int i = 0; i x [i + 1]) palauttaa false; palaa tosi; } yksityinen staattinen void sort (int [] x) {int j, a; // Kaikkien kokonaislukuarvojen lukuun ottamatta vasemmanpuoleisinta arvoa ... (int i = 1; i 0 && x [j - 1]> a) {// Vaihda vasen arvo - x [j - 1] - yksi paikka oikealla - // x [j]. x [j] = x [j - 1]; // Päivitä lisäyssijainti siirretyn arvon alkuperäiseen sijaintiin // (yksi paikka vasemmalle). j--; } // Lisää a kohtaan lisäyskohdassa (joka on joko alkuperäinen lisäys // sijainti tai viimeinen lisäysasento), jossa a on suurempi kuin // tai yhtä suuri kuin kaikki vasemmalla olevat arvot. x [j] = a; } assert isSorted (x): "taulukkoa ei ole lajiteltu"; }}

Luettelossa 4 esitetään a järjestellä() auttaja menetelmä, joka käyttää lisäyslaji algoritmi lajittelemaan kokonaislukuarvot. Olen käyttänyt väittävät tarkistaa jälkikäteen x lajitellaan ennen järjestellä() palaa soittajalle.

Listing 4: n esimerkki osoittaa väitteiden tärkeän ominaisuuden, että niiden toteuttaminen on yleensä kallista. Tästä syystä väitteet poistetaan yleensä käytöstä tuotantokoodissa. Luettelossa 4 isSorted () täytyy skannata koko matriisi, mikä voi olla aikaa vievää, jos kyseessä on pitkä matriisi.

Väitteet ja poikkeukset Java-sovelluksessa

Kehittäjät käyttävät väitteitä loogisesti mahdottomien tilanteiden dokumentointiin ja virheiden havaitsemiseen ohjelmointilogiikassaan. Suorituksen aikana käytössä oleva väite varoittaa kehittäjää logiikkavirheestä. Kehittäjä korjaa lähdekoodin korjaamaan logiikkavirheen ja kääntää sitten tämän koodin uudelleen.

Kehittäjät käyttävät Javan poikkeusmekanismia reagoimaan ei-kuolemaan johtaviin (esim. Muistin loppumiseen) ajonaikaisiin virheisiin, jotka voivat johtua ympäristötekijöistä, kuten tiedostosta, jota ei ole olemassa, tai huonosti kirjoitetusta koodista, kuten yrityksestä jakaa 0. Poikkeuskäsittelijä kirjoitetaan usein virheen palauttamiseksi sulavasti, jotta ohjelma voi jatkaa toimintaansa.

Väitteet eivät korvaa poikkeuksia. Toisin kuin poikkeukset, väitteet eivät tue virheiden palauttamista (väitteet yleensä pysäyttävät ohjelman suorituksen välittömästi -VäiteVirhe ei ole tarkoitus saada kiinni); ne ovat usein poissa käytöstä tuotantokoodissa; ja ne eivät yleensä näytä käyttäjäystävällisiä virheilmoituksia (vaikka tämä ei ole ongelma väittävät). On tärkeää tietää, milloin käytetään poikkeuksia väitteiden sijaan.

Milloin poikkeuksia käytetään

Oletetaan, että olet kirjoittanut sqrt () menetelmä, joka laskee argumenttinsa neliöjuuren. Ei-monimutkaisessa lukukontekstissa on mahdotonta ottaa negatiivisen luvun neliöjuuri. Siksi käytät väitettä menetelmän epäonnistumiseen, jos argumentti on negatiivinen. Harkitse seuraavaa koodinpätkää:

public double sqrt (double x) {väitä x> = 0: "x on negatiivinen"; // ...}

Ei ole asianmukaista käyttää väitettä argumentin vahvistamiseen tässä julkinen menetelmä. Väitteen tarkoituksena on havaita virheet ohjelmointilogiikassa eikä suojata menetelmää virheellisiltä argumenteilta. Lisäksi, jos väitteet poistetaan käytöstä, ei ole mitään keinoa käsitellä kielteisen argumentin ongelmaa. On parempi heittää poikkeus seuraavasti:

public double sqrt (double x) {if (x <0) heittää uuden IllegalArgumentExceptionin ("x on negatiivinen"); // ...}

Kehittäjä voi halutessaan antaa ohjelman käsitellä laitonta argumenttipoikkeusta tai yksinkertaisesti levittää sen ulos ohjelmasta, jossa ohjelmaa ajava työkalu näyttää virheilmoituksen. Luettuaan virhesanoman kehittäjä voi korjata minkä tahansa koodin, joka johti poikkeukseen.

Olet ehkä huomannut pienen eron väitteen ja virheiden havaitsemislogiikan välillä. Väittämätestit x> = 0, kun taas virheiden havaitsemislogiikka testaa x <0. Väite on optimistinen: Oletamme, että väite on OK. Sitä vastoin virheenilmaisulogiikka on pessimististä: Oletamme, että argumentti ei ole OK. Väitteet dokumentoivat oikean logiikan, kun taas poikkeukset dokumentoivat väärän ajonaikaisen käyttäytymisen.

Tässä opetusohjelmassa olet oppinut käyttämään väitteitä oikean ohjelmalogiikan dokumentoimiseksi. Olet myös oppinut, miksi väitteet eivät korvaa poikkeuksia, ja olet nähnyt esimerkin, jossa poikkeuksen käyttö olisi tehokkaampaa.

Tämän tarinan "Kuinka käyttää väitteitä Javassa" julkaisi alun perin JavaWorld.