Programmering

Sådan bruges påstande i Java

Skrivning af programmer, der fungerer korrekt i løbetid, kan være udfordrende. Dette skyldes, at vores antagelser om, hvordan vores kode vil opføre sig, når de udføres, ofte er forkerte. Brug af Java's påstandsfunktion er en måde at kontrollere, at din programmeringslogik er sund.

Denne vejledning introducerer Java-påstande. Du lærer først, hvad påstande er, og hvordan du specificerer og bruger dem i din kode. Derefter opdager du, hvordan du bruger påstande til at håndhæve forudsætninger og efterbetingelser. Endelig sammenligner du påstande med undtagelser og finder ud af, hvorfor du har brug for begge dele i din kode.

download Hent koden Download kildekoden for eksempler i denne vejledning. Oprettet af Jeff Friesen til JavaWorld.

Hvad er Java-påstande?

Før JDK 1.4 brugte udviklere ofte kommentarer til at dokumentere antagelser om programkorrekthed. Kommentarer er dog ubrugelige som en mekanisme til test og fejlretning af antagelser. Compileren ignorerer kommentarer, så der er ingen måde at bruge dem til bugsporing. Udviklere opdaterer ofte ikke kommentarer, når de ændrer kode.

I JDK 1.4 blev påstande introduceret som en ny mekanisme til test og debugging af antagelser om vores kode. I det væsentlige påstande er kompilerbare enheder, der udføres ved kørsel, forudsat at du har aktiveret dem til programtest. Du kan programmere påstande for at underrette dig om fejl, hvor fejlene opstår, hvilket reducerer den tid, du ellers ville bruge til at fejle fejl i et fejlagtigt program.

Påstande bruges til at kodificere de krav, der gør et program korrekt eller ikke ved test betingelser (Boolske udtryk) for ægte værdier og underrette udvikleren, når sådanne betingelser er falske. Brug af påstande kan i høj grad øge din tillid til korrektheden af ​​din kode.

Hvordan man skriver en påstand i Java

Påstande implementeres via hævde erklæring og java.lang.AssertionError klasse. Denne erklæring begynder med nøgleordet hævde og fortsætter med et boolsk udtryk. Det udtrykkes syntaktisk som følger:

hævde BooleanExpr;

Hvis BooleanExpr vurderes til sandt, intet sker, og udførelsen fortsætter. Hvis udtrykket dog evalueres til falsk, Påstand Fejl instantieres og kastes, som vist i liste 1.

Liste 1:AssertDemo.java (version 1)

offentlig klasse AssertDemo {public static void main (String [] args) {int x = -1; hævde x> = 0; }}

Påstanden i lister 1 indikerer udviklerens overbevisning om den variabel x indeholder en værdi, der er større end eller lig med 0. Dette er dog klart ikke tilfældet; det hævde erklæringens henrettelse resulterer i et kast Påstand Fejl.

Kompilere lister 1 (javac AssertDemo.java) og kør det med påstande aktiveret (java -ea AssertDemo). Du skal overholde følgende output:

Undtagelse i tråden "main" java.lang.AssertionError at AssertDemo.main (AssertDemo.java:6)

Denne meddelelse er noget kryptisk, idet den ikke identificerer, hvad der forårsagede Påstand Fejl at blive kastet. Hvis du vil have en mere informativ besked, skal du bruge hævde udsagn nedenfor:

hævde BooleanExpr : ekspr;

Her, ekspr er ethvert udtryk (inklusive en metodeopkald), der kan returnere en værdi - du kan ikke påberåbe en metode med en ugyldig returtype. Et nyttigt udtryk er en streng bogstavelig, der beskriver årsagen til fiasko, som vist i liste 2.

Liste 2:AssertDemo.java (version 2)

offentlig klasse AssertDemo {public static void main (String [] args) {int x = -1; hævde x> = 0: "x <0"; }}

Kompilere lister 2 (javac AssertDemo.java) og kør det med påstande aktiveret (java -ea AssertDemo). Denne gang skal du overholde følgende let udvidede output, som inkluderer årsagen til kastet Påstand Fejl:

Undtagelse i tråden "main" java.lang.AssertionError: x <0 at AssertDemo.main (AssertDemo.java:6)

For begge eksempler, kører AssertDemo uden -ea (aktiver påstande) -muligheden resulterer i ingen output. Når påstande ikke er aktiveret, udføres de ikke, selvom de stadig er til stede i klassefilen.

Forudsætninger og efterbetingelser

Påstande tester et programs antagelser ved at kontrollere, at dets forskellige forudsætninger og efterbetingelser ikke overtrædes, hvilket advarer udvikleren, når en overtrædelse opstår:

  • EN forudsætning er en betingelse, der skal evalueres til sand før udførelsen af ​​en eller anden kodesekvens. Forudsætninger sikrer, at opkaldere holder deres kontrakter med callees.
  • EN posttilstand er en betingelse, der skal evalueres til sand efter udførelsen af ​​en eller anden kodesekvens. Postforhold sikrer, at callees holder deres kontrakter med opkaldere.

Forudsætninger

Du kan håndhæve forudsætninger for offentlige konstruktører og metoder ved at foretage eksplicit kontrol og kaste undtagelser, når det er nødvendigt. For private hjælpermetoder kan du håndhæve forudsætninger ved at angive påstande. Overvej liste 3.

Liste 3:AssertDemo.java (version 3)

importere java.io.FileInputStream; importere java.io.InputStream; importere java.io.IOException; klasse PNG {/ ** * Opret en PNG-forekomst, læs den angivne PNG-fil og afkod den * til passende strukturer. * * @param filespec-sti og navn på PNG-fil, der skal læses * * @ kaster NullPointerException, når filspec er * nul * / PNG (String filespec) kaster IOException {// Håndhæv forudsætninger i ikke-private konstruktører og // metoder. hvis (filespec == null) smider ny NullPointerException ("filespec er null"); prøv (FileInputStream fis = ny FileInputStream (filespec)) {readHeader (fis); }} privat ugyldigt readHeader (InputStream er) kaster IOException {// Bekræft, at forudsætningen er opfyldt i private // hjælpemetoder. assert is! = null: "null overført til is"; }} offentlig klasse AssertDemo {public static void main (String [] args) throw IOException {PNG png = new PNG ((args.length == 0)? null: args [0]); }}

Det PNG klasse i Listing 3 er den minimale begyndelse af et bibliotek til læsning og afkodning af PNG (bærbare netværksgrafik) billedfiler. Konstruktøren sammenligner eksplicit filspec med nul, kaste NullPointerException når denne parameter indeholder nul. Pointen er at håndhæve den forudsætning, at filspec indeholder ikke nul.

Det er ikke hensigtsmæssigt at specificere hævde filespec! = null; fordi den forudsætning, der er nævnt i konstruktørens Javadoc, ikke (teknisk set) ville blive opfyldt, når påstande blev deaktiveret. (Faktisk ville det blive hædret fordi FileInputStream () ville kaste NullPointerException, men du bør ikke stole på udokumenteret adfærd.)

Imidlertid, hævde er passende i forbindelse med det private readHeader () hjælpermetoden, som til sidst vil blive afsluttet for at læse og afkode en PNG-fils 8-byte-overskrift. Forudsætningen for, at er altid videregives, vil en ikke-nul værdi altid holde.

Postbetingelser

Efterbetingelser specificeres typisk via påstande, uanset om metoden (eller konstruktøren) er offentlig eller ej. Overvej liste 4.

Liste 4:AssertDemo.java (version 4)

offentlig klasse AssertDemo {public static void main (String [] args) {int [] array = {20, 91, -6, 16, 0, 7, 51, 42, 3, 1}; sorter (array); for (int element: array) System.out.printf ("% d", element); System.out.println (); } privat statisk boolsk isSorted (int [] x) {for (int i = 0; i x [i + 1]) returnerer false; returner sandt; } privat statisk ugyldig sortering (int [] x) {int j, a; // For alle heltalværdier undtagen den venstre venstre værdi ... for (int i = 1; i 0 && x [j - 1]> a) {// Skift venstre værdi - x [j - 1] - en position til højre - // x [j]. x [j] = x [j - 1]; // Opdater indsæt position til forskudt værdis oprindelige position // (en position til venstre). j--; } // Indsæt en ved indsæt position (som enten er den indledende indsats // position eller den sidste indsatsposition), hvor a er større end // eller lig med alle værdier til venstre. x [j] = a; } assert isSorted (x): "array ikke sorteret"; }}

Liste 4 præsenterer a sortere() hjælper metode, der bruger indsættelsessort algoritme til at sortere en matrix af heltal værdier. Jeg har brugt hævde for at kontrollere postcondition af x bliver sorteret før sortere() vender tilbage til den, der ringer op.

Eksemplet i liste 4 viser et vigtigt kendetegn ved påstande, som er, at de typisk er dyre at udføre. Af denne grund er påstande normalt deaktiveret i produktionskoden. I liste 4, isSorted () skal scanne gennem hele arrayet, hvilket kan være tidskrævende i tilfælde af en lang array.

Påstande versus undtagelser i Java

Udviklere bruger påstande til at dokumentere logisk umulige situationer og opdage fejl i deres programmeringslogik. Ved kørsel advarer en aktiveret påstand en udvikler om en logisk fejl. Udvikleren refaktorer kildekoden for at rette den logiske fejl og kompilerer derefter denne kode igen.

Udviklere bruger Java's undtagelsesmekanisme til at reagere på ikke-fatale (f.eks. Løber tør for hukommelse) runtime-fejl, som kan være forårsaget af miljøfaktorer, såsom en fil, der ikke findes, eller af dårligt skrevet kode, såsom et forsøg på at dele med 0. En undtagelseshåndterer er ofte skrevet for at inddrive yndefuldt fra fejlen, så programmet kan fortsætte med at køre.

Påstande er ikke erstatning for undtagelser. I modsætning til undtagelser understøtter påstande ikke fejlgendannelse (påstande stopper typisk programudførelse med det samme -Påstand Fejl er ikke beregnet til at blive fanget); de er ofte deaktiveret i produktionskoden; og de viser typisk ikke brugervenlige fejlmeddelelser (selvom dette ikke er et problem med hævde). Det er vigtigt at vide, hvornår man skal bruge undtagelser snarere end påstande.

Hvornår skal man bruge undtagelser?

Antag at du har skrevet en sqrt () metode, der beregner kvadratroden af ​​dets argument. I en ikke-kompleks talkontekst er det umuligt at tage kvadratroden af ​​et negativt tal. Derfor bruger du en påstand for at mislykkes metoden, hvis argumentet er negativt. Overvej følgende kodefragment:

offentlig dobbelt sqrt (dobbelt x) {påstå x> = 0: "x er negativ"; // ...}

Det er upassende at bruge en påstand til at validere et argument i dette offentlig metode. En påstand er beregnet til at opdage fejl i programmeringslogikken og ikke for at beskytte en metode mod fejlagtige argumenter. Derudover, hvis påstande er deaktiveret, er der ingen måde at håndtere problemet med et negativt argument på. Det er bedre at kaste en undtagelse som følger:

offentlig dobbelt sqrt (dobbelt x) {hvis (x <0) smider nyt IllegalArgumentException ("x er negativ"); // ...}

Udvikleren kan vælge at få programmet til at håndtere den ulovlige argumentundtagelse eller blot udbrede det ud af programmet, hvor en fejlmeddelelse vises af det værktøj, der kører programmet. Efter at have læst fejlmeddelelsen kan udvikleren rette den kode, der førte til undtagelsen.

Du har muligvis bemærket en subtil forskel mellem påstanden og fejldetekteringslogikken. Påstandstestene x> = 0, hvorimod logikken til fejldetektering tester x <0. Påstanden er optimistisk: Vi antager, at argumentet er OK. I modsætning hertil er fejldetektionslogikken pessimistisk: Vi antager, at argumentet ikke er OK. Påstande dokumenterer korrekt logik, mens undtagelser dokumenterer forkert runtime-opførsel.

I denne vejledning har du lært, hvordan du bruger påstande til at dokumentere korrekt programlogik. Du har også lært, hvorfor påstande ikke erstatning for undtagelser, og du har set et eksempel, hvor brugen af ​​en undtagelse ville være mere effektiv.

Denne historie, "Sådan bruges påstande i Java", blev oprindeligt udgivet af JavaWorld.

$config[zx-auto] not found$config[zx-overlay] not found