Programavimas

Kaip naudoti teiginius „Java“

Tinkamai veikiančių programų rašymas gali būti sudėtingas. Taip yra todėl, kad mūsų prielaidos apie tai, kaip mūsų kodas elgsis vykdant, dažnai yra klaidingos. „Java“ teiginių funkcijos naudojimas yra vienas iš būdų patikrinti, ar jūsų programavimo logika yra patikima.

Šioje pamokoje pristatomi „Java“ teiginiai. Pirmiausia sužinosite, kas yra teiginiai ir kaip juos nurodyti ir naudoti savo kode. Tada sužinosite, kaip naudoti teiginius, norint įgyvendinti išankstines ir vėlesnes sąlygas. Galiausiai palyginsite teiginius su išimtimis ir sužinosite, kodėl kode jums reikia abiejų.

atsisiųsti Gauti kodą Atsisiųskite šios pamokos pavyzdžių šaltinio kodą. Sukūrė Jeffas Friesenas, skirtas „JavaWorld“.

Kas yra „Java“ teiginiai?

Prieš JDK 1.4 kūrėjai dažnai naudojo komentarus dokumentuodami prielaidas apie programos teisingumą. Tačiau komentarai yra nenaudingi kaip prielaidų tikrinimo ir derinimo mechanizmas. Kompiliatorius nepaiso komentarų, todėl jokiu būdu negalima jų naudoti klaidoms aptikti. Kūrėjai taip pat dažnai neatnaujina komentarų keisdami kodą.

JDK 1.4 versijoje teiginiai buvo įvesti kaip naujas mechanizmas, leidžiantis patikrinti ir derinti prielaidas apie mūsų kodą. Iš esmės, tvirtinimai yra kompiliuojami objektai, kurie vykdomi vykdymo metu, darant prielaidą, kad įgalinote juos atlikti programos testavimą. Galite užprogramuoti teiginius, kad praneštumėte apie klaidas ten, kur atsiranda klaidų, žymiai sutrumpindami laiką, kurį kitu atveju praleistumėte derindami nepavykusią programą.

Teiginiai naudojami koduojant reikalavimus, kurie, bandydami, daro programą teisingą ar ne sąlygos (Loginės išraiškos) tikrosioms vertybėms ir pranešti kūrėjui, kai tokios sąlygos yra klaidingos. Teiginių naudojimas gali labai padidinti jūsų pasitikėjimą kodo teisingumu.

Kaip parašyti tvirtinimą „Java“

Teiginiai įgyvendinami per tvirtinti pareiškimas ir java.lang.AssertionError klasė. Šis teiginys prasideda raktiniu žodžiu tvirtinti ir tęsia Būlio išraiška. Jis sintaksiškai išreiškiamas taip:

tvirtinti Bulio logotipas;

Jei Bulio logotipas įvertina kaip tiesa, nieko nevyksta ir vykdymas tęsiasi. Jei išraiška vertinama kaip klaidinga, „AssertionError“ yra išaiškinamas ir išmetamas, kaip parodyta 1 sąraše.

1 sąrašas:AssertDemo.java (1 versija)

public class „AssertDemo“ {public static void main (String [] args) {int x = -1; tvirtinti x> = 0; }}

1 sąraše esantis teiginys rodo kūrėjo įsitikinimą, kad kintamasis x yra vertė, didesnė arba lygi 0. Tačiau tai akivaizdžiai nėra tas atvejis; tvirtinti pareiškimo vykdymo rezultatas yra metamas „AssertionError“.

Sudaryti 1 sąrašą (javac AssertDemo.java) ir paleiskite jį su įgalintais teiginiais (java -ea AssertDemo). Turėtumėte stebėti šį rezultatą:

Išimtis temoje „main“ java.lang.AssertionError at AssertDemo.main (AssertDemo.java:6)

Ši žinutė yra šiek tiek paslaptinga, nes nenustato, kas sukėlė „AssertionError“ būti išmestam. Jei norite daugiau informatyvaus pranešimo, naudokite tvirtinti pareiškimas, išreikštas žemiau:

tvirtinti Bulio logotipas : išr;

Čia išr yra bet kokia išraiška (įskaitant metodo iškvietimą), galinti grąžinti vertę - metodo negalite iškviesti naudodami a tuštuma grąžinimo tipas. Naudinga išraiška yra eilutės literalas, apibūdinantis gedimo priežastį, kaip parodyta 2 sąraše.

2 sąrašas:AssertDemo.java (2 versija)

public class „AssertDemo“ {public static void main (String [] args) {int x = -1; teigti x> = 0: "x <0"; }}

Sudaryti 2 sąrašą (javac AssertDemo.java) ir paleiskite jį su įgalintais teiginiais (java -ea AssertDemo). Šį kartą turėtumėte stebėti šią šiek tiek išplėstą išvestį, kurioje yra metimo priežastis „AssertionError“:

Išimtis temoje „main“ java.lang.AssertionError: x <0 at AssertDemo.main (AssertDemo.java:6)

Bet kuriuo atveju, bėgimas „AssertDemo“ be -ea (įgalinti teiginius) parinktis neišvesties. Kai teiginiai neįgalinami, jie nevykdomi, nors jie vis dar yra klasės faile.

Išankstinės ir vėlesnės sąlygos

Tvirtinimai patikrina programos prielaidas, patikrindami, ar nepažeidžiamos įvairios jos išankstinės ir vėlesnės sąlygos, ir įspėja kūrėją, kai įvyksta pažeidimas:

  • A išankstinė sąlyga yra sąlyga, kurią prieš vykdant tam tikrą kodų seką reikia įvertinti tiesą. Išankstinės sąlygos užtikrina, kad skambinantieji laikytųsi sutarčių su sutuoktiniais.
  • A postcondition yra sąlyga, kuri turi būti įvertinta kaip teisinga atlikus tam tikrą kodų seką. Vėlesnės sąlygos užtikrina, kad sutuoktiniai laikytųsi savo sutarčių su skambinančiaisiais.

Išankstinės sąlygos

Galite įgyvendinti išankstines sąlygas viešiesiems konstruktoriams ir metodams, atlikdami aiškius patikrinimus ir, jei reikia, išimtis. Privačių pagalbininkų metodams galite įgyvendinti prielaidas nurodydami teiginius. Apsvarstykite 3 sąrašą.

3 sąrašas:AssertDemo.java (3 versija)

importuoti java.io.FileInputStream; importuoti java.io.InputStream; importuoti java.io.IOException; klasės PNG {/ ** * Sukurkite PNG egzempliorių, perskaitykite nurodytą PNG failą ir iššifruokite * jį į tinkamas struktūras. * * @param filespec kelias ir perskaityto PNG failo pavadinimas * * @throws NullPointerException kai failo specifikacija yra * niekinis * / PNG (String filespec) išmeta „IOException“ {// Priverstinių sąlygų vykdymas neprivačiuose konstruktoriuose ir // metoduose. if (filespec == null) mesti naują NullPointerException ("failų specifikacija yra nulinė"); pabandykite (FileInputStream fis = new FileInputStream (filespec)) {readHeader (fis); }} private void readHeader („InputStream is“) išmeta „IOException“ {// Patvirtinkite, kad būtina sąlyga tenkinama privačiuose // pagalbininkų metoduose. teigti yra! = null: "null perduota yra"; }} public class AssertDemo {public static void main (String [] args) meta IOException {PNG png = naujas PNG ((args.length == 0)? null: args [0]); }}

PNG 3 sąrašo klasė yra minimali bibliotekos pradžia, skirta PNG (nešiojamojo tinklo grafikos) vaizdų failams skaityti ir dekoduoti. Konstruktorius aiškiai lygina failo specifikacija su niekinis, metimas „NullPointerException“ kai šiame parametre yra niekinis. Esmė yra įgyvendinti išankstinę sąlygą failo specifikacija nėra niekinis.

Netikslinga nurodyti teigti filespec! = null; nes išankstinė sąlyga, minima konstruktoriaus „Javadoc“, nebus (techniškai) laikomasi, kai teiginiai buvo išjungti. (Tiesą sakant, tai būtų pagerbta, nes „FileInputStream“ () mėtytų „NullPointerException“, bet neturėtumėte priklausyti nuo nedokumentuoto elgesio.)

Tačiau tvirtinti yra tinkamas privataus kontekste readHeader () pagalbinis metodas, kuris galiausiai bus baigtas perskaityti ir iššifruoti PNG failo 8 baitų antraštę. Išankstinė sąlyga, kad yra visada bus perduodama ne nulinė vertė.

Postconditions

Vėlesnės sąlygos paprastai nurodomos tvirtinant, neatsižvelgiant į tai, ar metodas (ar konstruktorius) yra viešas, ar ne. Apsvarstykite 4 sąrašą.

4 sąrašas:AssertDemo.java (4 versija)

public class „AssertDemo“ {public static void main (String [] args) {int [] masyvas = {20, 91, -6, 16, 0, 7, 51, 42, 3, 1}; rūšiuoti (masyvas); for (int elementas: masyvas) System.out.printf ("% d", elementas); System.out.println (); } private static Boolean isSorted (int [] x) {for (int i = 0; i x [i + 1]) grąžina klaidingą; grįžti tiesa; } privatus statinis tuštumas rūšiuoti (int [] x) {int j, a; // Visoms sveikojo skaičiaus reikšmėms, išskyrus kairiausią reikšmę ... (int i = 1; i 0 && x [j - 1]> a) {// Shift left value - x [j - 1] - viena pozicija dešinėje - // x [j]. x [j] = x [j - 1]; // Atnaujinkite įterpimo poziciją į pradinę perkeltos vertės padėtį // (viena padėtis kairėje). j--; } // Įterpti a įterpimo vietoje (kuri yra arba pradinė įterpimo // padėtis, arba galutinė įterpimo padėtis), kur a yra didesnis nei // arba lygus visoms vertėms kairėje. x [j] = a; } assert isSorted (x): "masyvas nerūšiuotas"; }}

4 sąraše pateikiami a rūšiuoti () pagalbininkas metodas, kuris naudoja įterpimo rūšiavimas algoritmas išrikiuoti sveikųjų skaičių masyvą. Aš naudojau tvirtinti patikrinti vėlesnę būklę x prieš tai buvo rūšiuojami rūšiuoti () grįžta pas savo skambintoją.

4 sąraše pateiktas pavyzdys rodo svarbią teiginių ypatybę, ty tai, kad juos paprastai brangu vykdyti. Dėl šios priežasties teiginiai yra išjungiami gamybos kode. 4 sąraše isSorted () turi nuskaityti visą masyvą, o tai gali užtrukti ilgai, jei yra ilgas masyvas.

Teiginiai ir išimtys „Java“

Kūrėjai naudoja teiginius, kad dokumentuotų logiškai neįmanomas situacijas ir aptiktų klaidų savo programavimo logikoje. Vykdymo metu įgalintas tvirtinimas įspėja kūrėją apie logikos klaidą. Kūrėjas pertvarko šaltinio kodą, kad ištaisytų logikos klaidą, ir tada kompiliuoja šį kodą.

Kūrėjai naudoja „Java“ išimties mechanizmą, kad reaguotų į nemirtinas (pvz., Atminties trūkumo) vykdymo laiko klaidas, kurias gali sukelti aplinkos veiksniai, pvz., Neegzistuojantis failas, arba blogai parašytas kodas, pavyzdžiui, bandymas padalyti iš 0. Išimčių tvarkytuvas dažnai rašomas, kad grakščiai atsigautų po klaidos, kad programa galėtų toliau veikti.

Teiginiai nepakeičia išimčių. Skirtingai nei išimtys, teiginiai nepalaiko klaidų atkūrimo (teiginiai paprastai iškart sustabdo programos vykdymą -„AssertionError“ nėra skirtas pagauti); jie dažnai neįgalūs pagal gamybos kodą; ir jie paprastai nerodo patogių klaidų pranešimų (nors tai nėra problema tvirtinti). Svarbu žinoti, kada naudoti išimtis, o ne teiginius.

Kada naudoti išimtis

Tarkime, kad parašėte a sqrt () metodas, kuris apskaičiuoja savo argumento kvadratinę šaknį. Nesudėtingo skaičiaus kontekste neįmanoma paimti neigiamo skaičiaus kvadratinės šaknies. Todėl, jei argumentas yra neigiamas, jūs naudojate teiginį, kad metodas nepavyktų. Apsvarstykite šį kodo fragmentą:

public double sqrt (double x) {teigti x> = 0: "x yra neigiamas"; // ...}

Netinkama naudoti teiginį, kad patvirtintumėte argumentą visuomenės metodas. Teiginys skirtas aptikti programavimo logikos klaidas, o ne apsaugoti metodą nuo klaidingų argumentų. Be to, jei teiginiai yra neįgalūs, jokiu būdu negalima išspręsti neigiamo argumento problemos. Geriau išmesti išimtį taip:

public double sqrt (double x) {if (x <0) thrown new IllegalArgumentException ("x yra neigiamas"); // ...}

Kūrėjas gali pasirinkti, kad programa tvarkytų neteisėtų argumentų išimtį, arba tiesiog išplės ją iš programos, kur klaidos pranešimas rodomas programą paleidžiančiame įrankyje. Perskaičius klaidos pranešimą, kūrėjas gali išspręsti bet kokį kodą, dėl kurio atsirado išimtis.

Galbūt pastebėjote subtilų teiginio ir klaidų aptikimo logikos skirtumą. Teigimo testai x> = 0, o klaidų aptikimo logikos testai x <0. Šis teiginys yra optimistiškas: mes manome, kad argumentas yra tinkamas. Priešingai, klaidų aptikimo logika yra pesimistinė: manome, kad argumentas nėra tinkamas. Teiginiai dokumentuoja teisingą logiką, o išimtys - neteisingą vykdymo laiko elgesį.

Šioje pamokoje sužinojote, kaip naudoti teiginius, norint dokumentuoti teisingą programos logiką. Jūs taip pat sužinojote, kodėl teiginiai nepakeičia išimčių, ir matėte pavyzdį, kai išimtį naudoti būtų efektyviau.

Šią istoriją „Kaip naudoti teiginius„ Java ““ iš pradžių paskelbė „JavaWorld“.