Programmering

Hvordan bruke påstander i Java

Å skrive programmer som fungerer riktig ved kjøretid, kan være utfordrende. Dette er fordi antagelsene våre om hvordan koden vår vil oppføre seg når de kjøres ofte er feil. Å bruke Java's påstandsfunksjon er en måte å bekrefte at programmeringslogikken din er god.

Denne opplæringen introduserer Java-påstander. Du får først vite hva påstander er og hvordan du spesifiserer og bruker dem i koden din. Deretter vil du oppdage hvordan du kan bruke påstander for å håndheve forutsetninger og etterbetingelser. Til slutt vil du sammenligne påstander med unntak, og finne ut hvorfor du trenger begge deler i koden din.

last ned Få koden Last ned kildekoden for eksempler i denne veiledningen. Skapt av Jeff Friesen for JavaWorld.

Hva er Java-påstander?

Før JDK 1.4 brukte utviklere ofte kommentarer til å dokumentere antagelser om programkorrekthet. Kommentarer er imidlertid ubrukelige som en mekanisme for å teste og feilsøke antagelser. Kompilatoren ignorerer kommentarer, så det er ingen måte å bruke dem til deteksjon av feil. Utviklere oppdaterer ofte ikke kommentarer når de endrer kode.

I JDK 1.4 ble påstander introdusert som en ny mekanisme for å teste og feilsøke antagelser om koden vår. I hovedsak, påstander er kompilerbare enheter som kjøres ved kjøretid, forutsatt at du har aktivert dem for programtesting. Du kan programmere påstander for å varsle deg om feil der feilene oppstår, noe som reduserer tiden du ellers ville brukt til å feilsøke et mislykket program.

Påstander brukes til å kodifisere kravene som gjør et program riktig eller ikke ved testing forhold (Boolske uttrykk) for sanne verdier, og varsle utvikleren når slike forhold er falske. Bruk av påstander kan øke tilliten din til korrektheten av koden din.

Hvordan skrive en påstand i Java

Påstander implementeres via hevder uttalelse og java.lang.AssertionError klasse. Denne påstanden begynner med nøkkelordet hevder og fortsetter med et boolsk uttrykk. Det uttrykkes syntaktisk som følger:

hevder BooleanExpr;

Hvis BooleanExpr evaluerer til sant, ingenting skjer og utførelse fortsetter. Hvis uttrykket evalueres til usant, men Påstand Feil blir instantiert og kastet, som vist i Listing 1.

Oppføring 1:AssertDemo.java (versjon 1)

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

Påstanden i oppføring 1 indikerer utviklerens tro på at variabelen x inneholder en verdi som er større enn eller lik 0. Dette er imidlertid tydeligvis ikke tilfelle; de hevder utsagnets henrettelse resulterer i et kast Påstand Feil.

Kompilere oppføring 1 (javac AssertDemo.java) og kjør den med påstander aktivert (java -ea AssertDemo). Du bør følge følgende utdata:

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

Denne meldingen er noe kryptisk ved at den ikke identifiserer hva som forårsaket Påstand Feil å bli kastet. Hvis du vil ha en mer informativ melding, bruker du hevder uttalelse uttrykt nedenfor:

hevder BooleanExpr : ekspr;

Her, ekspr er et hvilket som helst uttrykk (inkludert en metodeinnkallelse) som kan returnere en verdi - du kan ikke påkalle en metode med en tomrom returtype. Et nyttig uttrykk er en streng bokstavelig som beskriver årsaken til feil, som vist i Listing 2.

Oppføring 2:AssertDemo.java (versjon 2)

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

Kompilere oppføring 2 (javac AssertDemo.java) og kjør den med påstander aktivert (java -ea AssertDemo). Denne gangen bør du observere følgende litt utvidede utdata, som inkluderer årsaken til kastet Påstand Feil:

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

For begge eksemplene, løping AssertDemo uten -ea (aktiver påstander) alternativet gir ingen utdata. Når påstander ikke er aktivert, blir de ikke utført, selv om de fremdeles er tilstede i klassefilen.

Forutsetninger og etterbetingelser

Påstander tester antagelsene til et program ved å bekrefte at dets ulike forutsetninger og etterbetingelser ikke blir brutt, og varsler utvikleren når det oppstår et brudd:

  • EN forutsetning er en tilstand som må evalueres til sant før utførelsen av en eller annen kodesekvens. Forutsetninger sørger for at innringere holder sine kontrakter med callees.
  • EN posttilstand er en tilstand som må evalueres til sant etter utførelsen av en eller annen kodesekvens. Postforhold sørger for at callees holder sine kontrakter med innringere.

Forutsetninger

Du kan håndheve forutsetninger for offentlige konstruktører og metoder ved å gjøre eksplisitte kontroller og kaste unntak når det er nødvendig. For private hjelpermetoder kan du håndheve forutsetninger ved å spesifisere påstander. Vurder oppføring 3.

Oppføring 3:AssertDemo.java (versjon 3)

importere java.io.FileInputStream; importere java.io.InputStream; importere java.io.IOException; klasse PNG {/ ** * Opprett en PNG-forekomst, les spesifisert PNG-fil og dekoder * den til passende strukturer. * * @param filespec-bane og navn på PNG-fil som skal leses * * @ kaster NullPointerException når filespec er * null * / PNG (String filespec) kaster IOException {// Handheve forutsetninger i ikke-private konstruktører og // metoder. hvis (filespec == null) kaster ny NullPointerException ("filespec er null"); prøv (FileInputStream fis = ny FileInputStream (filespec)) {readHeader (fis); }} private void readHeader (InputStream is) kaster IOException {// Bekreft at forutsetningen er oppfylt i private // hjelpermetoder. assert is! = null: "null overført til er"; }} offentlig klasse AssertDemo {public static void main (String [] args) kaster IOException {PNG png = new PNG ((args.length == 0)? null: args [0]); }}

De PNG klasse i Listing 3 er den minimale begynnelsen på et bibliotek for lesing og dekoding av PNG (bærbare nettverksgrafikk) bildefiler. Konstruktøren sammenligner eksplisitt filespec med null, kaster NullPointerException når denne parameteren inneholder null. Poenget er å håndheve forutsetningen om at filespec ikke inneholder null.

Det er ikke aktuelt å spesifisere hevde filespec! = null; fordi forutsetningen nevnt i konstruktørens Javadoc ikke (teknisk) ville bli respektert når påstander ble deaktivert. (Faktisk ville det bli æret fordi FileInputStream () ville kaste NullPointerException, men du bør ikke stole på papirløs oppførsel.)

Derimot, hevder er passende i sammenheng med det private readHeader () hjelpermetoden, som til slutt vil fullføres for å lese og dekode en PNG-fils 8-byte-overskrift. Forutsetningen det er alltid passeres vil en ikke-null verdi alltid holde.

Postforhold

Postforhold spesifiseres vanligvis via påstander, uansett om metoden (eller konstruktøren) er offentlig eller ikke. Vurder oppføring 4.

Oppføring 4:AssertDemo.java (versjon 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]) returner false; returner sant; } privat statisk tomt sort (int [] x) {int j, a; // For alle heltalsverdier unntatt verdien lengst til venstre ... for (int i = 1; i 0 && x [j - 1]> a) {// Skift venstre verdi - x [j - 1] - en posisjon til høyre - // x [j]. x [j] = x [j - 1]; // Oppdater innsettingsposisjon til forskyvet verdis opprinnelige posisjon // (en posisjon til venstre). j--; } // Sett inn en ved innsettingsposisjon (som enten er den innledende innsettingsposisjonen // eller den endelige innsettingsposisjonen), der a er større enn // eller lik alle verdiene til venstre. x [j] = a; } assert isSorted (x): "array not sorted"; }}

Oppføring 4 presenterer a sortere() hjelpermetode som bruker innsettingssort algoritme for å sortere en rekke heltalsverdier. Jeg har brukt hevder for å sjekke posttilstanden til x blir sortert før sortere() går tilbake til den som ringer.

Eksemplet i oppføring 4 demonstrerer en viktig egenskap ved påstander, som er at de vanligvis er dyre å utføre. Av denne grunn er påstander vanligvis deaktivert i produksjonskoden. I oppføring 4, isSorted () må skanne gjennom hele matrisen, noe som kan være tidkrevende i tilfelle en lang matrise.

Påstander mot unntak i Java

Utviklere bruker påstander for å dokumentere logisk umulige situasjoner og oppdage feil i programmeringslogikken. Ved kjøretid varsler en aktivert påstand en utvikler om en logikkfeil. Utvikleren refaktorer kildekoden for å fikse logikkfeilen, og kompilerer deretter denne koden på nytt.

Utviklere bruker Java's unntaksmekanisme for å svare på ikke-fatale (f.eks. Tom for minne) kjøretidsfeil, som kan være forårsaket av miljøfaktorer, for eksempel en fil som ikke eksisterer, eller av dårlig skrevet kode, for eksempel et forsøk på å dele med 0. En unntakshåndterer skrives ofte for å gjenopprette elegant fra feilen slik at programmet kan fortsette å kjøre.

Påstander er ingen erstatning for unntak. I motsetning til unntak støtter påstander ikke feilgjenoppretting (påstander stopper vanligvis programutførelsen umiddelbart -Påstand Feil er ikke ment å bli tatt); de er ofte deaktivert i produksjonskode; og de viser vanligvis ikke brukervennlige feilmeldinger (selv om dette ikke er et problem med hevder). Det er viktig å vite når du skal bruke unntak i stedet for påstander.

Når skal du bruke unntak

Anta at du har skrevet a sqrt () metode som beregner kvadratroten av argumentet. I en ikke-kompleks tallsammenheng er det umulig å ta kvadratroten av et negativt tall. Derfor bruker du en påstand for å mislykkes metoden hvis argumentet er negativt. Tenk på følgende kodefragment:

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

Det er upassende å bruke en påstand for å validere et argument i dette offentlig metode. En påstand er ment å oppdage feil i programmeringslogikken og ikke å beskytte en metode mot feilaktige argumenter. Dessuten, hvis påstander er deaktivert, er det ingen måte å håndtere problemet med et negativt argument. Det er bedre å kaste et unntak som følger:

offentlig dobbel sqrt (dobbel x) {hvis (x <0) kaster ny IllegalArgumentException ("x er negativ"); // ...}

Utvikleren kan velge å få programmet til å håndtere det ulovlige argument unntaket, eller bare overføre det ut av programmet der en feilmelding vises av verktøyet som kjører programmet. Når du leser feilmeldingen, kan utvikleren fikse hvilken kode som førte til unntaket.

Du har kanskje lagt merke til en subtil forskjell mellom påstanden og feildeteksjonslogikken. Påstandstestene x> = 0, mens logikk for feiloppdagelse tester x <0. Påstanden er optimistisk: Vi antar at argumentet er OK. I motsetning til dette er feildeteksjonslogikken pessimistisk: Vi antar at argumentet ikke er OK. Påstander dokumenterer korrekt logikk, mens unntak dokumenterer feil kjøretid.

I denne veiledningen har du lært hvordan du bruker påstander for å dokumentere riktig programlogikk. Du har også lært hvorfor påstander ikke erstatter unntak, og du har sett et eksempel der bruk av unntak ville være mer effektivt.

Denne historien, "Hvordan bruke påstander i Java", ble opprinnelig utgitt av JavaWorld.

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