Introduktion til javax.measure

1. Oversigt

I denne artikel introducerer vi Units of Measurement API - som giver en samlet måde at repræsentere mål og enheder i Java på.

Når vi arbejder med et program, der indeholder fysiske mængder, er vi nødt til at fjerne usikkerheden omkring de anvendte enheder. Det er vigtigt, at vi administrerer både nummeret og dets enhed for at forhindre fejl i beregningerne.

JSR-363 (tidligere JSR-275 eller javax. mål bibliotek) hjælper os med at spare udviklingstiden og samtidig gøre koden mere læsbar.

2. Maven-afhængigheder

Lad os bare starte med Maven-afhængigheden for at trække i biblioteket:

 javax.measenhed-api 1.0 

Den nyeste version kan findes på Maven Central.

Det enhed-api projektet indeholder et sæt grænseflader, der definerer, hvordan man arbejder med mængder og enheder. I eksemplerne bruger vi referenceimplementeringen af JSR-363, som er enhed-ri:

 tec. enheder enhed-ri 1.0.3 

3. Udforskning af API

Lad os se på eksemplet, hvor vi vil opbevare vand i en tank.

Den ældre implementering vil se sådan ud:

offentlig klasse WaterTank {public void setWaterQuantity (dobbelt mængde); }

Som vi kan se, nævner ovenstående kode ikke enheden for vandmængde og er ikke egnet til nøjagtige beregninger på grund af tilstedeværelsen af dobbelt type.

Hvis en udvikler fejlagtigt overfører værdien med en anden måleenhed end den, vi forventer, kan det føre til alvorlige fejl i beregningerne. Sådanne fejl er meget svære at opdage og løse.

Det JSR-363 API giver os Antal og Enhed grænseflader, der løser denne forvirring og efterlader denne slags fejl uden for vores programs anvendelsesområde.

3.1. Simpelt eksempel

Lad os nu undersøge og se, hvordan dette kan være nyttigt i vores eksempel.

Som nævnt tidligere, JSR-363 indeholder det Antal interface, der repræsenterer en kvantitativ egenskab såsom volumen eller areal. Biblioteket har adskillige undergrænseflader, der modellerer de mest anvendte kvantificerbare attributter. Nogle eksempler er: Bind, Længde, Elektrisk ladning, Energi, Temperatur.

Vi kan definere Antal objekt, som skal gemme mængden af ​​vand i vores eksempel:

offentlig klasse WaterTank {public void setCapacityMeasure (Quantity capacityMeasure); }

udover det Antal interface, vi kan også bruge Enhed interface til at identificere måleenheden for en ejendom. Definitioner for ofte anvendte enheder findes i enhed-ri bibliotek, såsom: KELVIN, MÅLER, NEWTON, CELSIUS.

Et objekt af typen Antal har metoder til at hente enheden og værdien: getUnit () og getValue ().

Lad os se et eksempel for at indstille værdien for mængden af ​​vand:

@Test offentlig ugyldighed givenQuantity_whenGetUnitAndConvertValue_thenSuccess () {WaterTank waterTank = new WaterTank (); waterTank.setCapacityMeasure (Quantities.getQuantity (9.2, LITER)); assertEquals (LITER, waterTank.getCapacityMeasure (). getUnit ()); Mængde waterCapacity = waterTank.getCapacityMeasure (); dobbelt volumeInLitre = waterCapacity.getValue (). doubleValue (); assertEquals (9.2, volumeInLitre, 0.0f); }

Vi kan også konvertere dette Bind i LITER til enhver anden enhed hurtigt:

dobbelt volumeInMilliLitre = waterCapacity .to (MetricPrefix.MILLI (LITER)). getValue (). doubleValue (); assertEquals (9200.0, volumeInMilliLitre, 0.0f);

Men når vi forsøger at konvertere vandmængden til en anden enhed - som ikke er af typen Bind, vi får en kompileringsfejl:

// kompileringsfejl waterCapacity.to (MetricPrefix.MILLI (KILOGRAM));

3.2. Klasseparameterisering

For at opretholde dimensionens konsistens drager rammen naturligvis fordel af generiske stoffer.

Klasser og grænseflader parametriseres efter deres mængdetype, hvilket gør det muligt at få vores enheder kontrolleret ved kompileringstidspunktet. Compileren giver en fejl eller advarsel baseret på hvad den kan identificere:

Enhedskilometer = MetricPrefix.KILO (METER); Enhedscentimeter = MetricPrefix.CENTI (LITER); // kompileringsfejl

Der er altid en mulighed for at omgå typekontrollen ved hjælp af asType () metode:

Enhedstommer = CENTI (METER) .tider (2.54) .asType (Length.class);

Vi kan også bruge et jokertegn, hvis vi ikke er sikre på typen af ​​mængde:

Enhed kelvinPerSec = KELVIN.divide (SECOND);

4. Enhedskonvertering

Enheds kan hentes fra SystemOfUnits. Referenceimplementeringen af ​​specifikationen indeholder Enheder implementering af grænsefladen, der giver et sæt statiske konstanter, der repræsenterer de mest anvendte enheder.

Derudover kan vi også oprette en helt ny brugerdefineret enhed eller oprette en enhed ved at anvende algebraiske operationer på eksisterende enheder.

Fordelen ved at bruge en standardenhed er, at vi ikke løber ind i konverteringsgrupper.

Vi kan også bruge præfikser eller multiplikatorer fra MetricPrefix klasse, ligesom KILO (enhed) og CENTI (enhed), som svarer til at multiplicere og dividere med en effekt på henholdsvis 10.

For eksempel kan vi definere "Kilometer" og "Centimeter" som:

Enhedskilometer = MetricPrefix.KILO (METER); Enhedscentimeter = MetricPrefix.CENTI (METER);

Disse kan bruges, når en enhed, vi ønsker, ikke er tilgængelig direkte.

4.1. Brugerdefinerede enheder

Under alle omstændigheder, hvis en enhed ikke findes i enhedssystemet, kan vi oprette nye enheder med nye symboler:

  • Alternativ enhed - en ny enhed med samme dimension men anderledes symbol og natur
  • Produktenhed - en ny enhed oprettet som et produkt af andre enheds rationelle kræfter

Lad os oprette nogle brugerdefinerede enheder ved hjælp af disse klasser. Et eksempel på Alternativ enhed for tryk:

@Test offentlig ugyldighed givenUnit_whenAlternateUnit_ThenGetAlternateUnit () {Enhed PASCAL = NEWTON.divide (METRE.pow (2)) .alternate ("Pa"). AsType (Pressure.class); assertTrue (SimpleUnitFormat.getInstance (). parse ("Pa") .equals (PASCAL)); }

Tilsvarende et eksempel på Produktenhed og dets konvertering:

@Test offentlig ugyldighed givenUnit_whenProduct_ThenGetProductUnit () {Enhed squareMetre = METRE.multiply (METER) .asType (Area.class); Mængdelinje = Quantities.getQuantity (2, METER); assertEquals (line.multiply (line) .getUnit (), squareMetre); }

Her har vi oprettet en kvadratmeter sammensat enhed ved at multiplicere MÅLER med sig selv.

Dernæst giver rammerne til enhedstyperne også en UnitConverter klasse, som hjælper os med at konvertere en enhed til en anden eller oprette en ny afledt enhed kaldet TransformedUnit.

Lad os se et eksempel for at dreje enheden med en dobbelt værdi fra meter til kilometer:

@Test offentlig ugyldighed givenMeters_whenConvertToKilometer_ThenConverted () {dobbelt distanceInMeters = 50.0; UnitConverter metreToKilometre = METRE.getConverterTo (MetricPrefix.KILO (METER)); dobbelt distanceInKilometers = metreToKilometre.convert (distanceInMeters); assertEquals (0,05, distanceInKilometers, 0,00f); }

For at lette utvetydig elektronisk kommunikation af mængder med deres enheder leverer biblioteket Enhedsformat interface, som forbinder systemdækkende etiketter med Enheder.

Lad os kontrollere etiketterne på nogle systemenheder ved hjælp af SimpleUnitFormat implementering:

@Test offentlig ugyldighed givenSymbol_WhenCompareToSystemUnit_ThenSuccess () {assertTrue (SimpleUnitFormat.getInstance (). Parse ("kW") .equals (MetricPrefix.KILO (WATT))); assertTrue (SimpleUnitFormat.getInstance (). parse ("ms"). ligestilling (SECOND.divide (1000))); }

5. Udførelse af operationer med mængder

Det Antal interface indeholder metoder til de mest almindelige matematiske operationer: tilføje(), trække fra(), formere sig(), dele(). Ved hjælp af disse kan vi udføre operationer mellem Antal genstande:

@Test offentlig ugyldighed givenUnits_WhenAdd_ThenSuccess () {Quantity total = Quantities.getQuantity (2, METER) .add (Quantities.getQuantity (3, METER)); assertEquals (total.getValue (). intValue (), 5); }

Metoderne bekræfter også Enheder af de genstande, de arbejder på. For eksempel vil forsøg på at multiplicere meter med liter resultere i en kompileringsfejl:

// kompileringsfejl Quantity total = Quantities.getQuantity (2, METER) .add (Quantities.getQuantity (3, LITER));

På den anden side kan to objekter udtrykt i enheder, der har samme dimension, tilføjes:

Mængde totalKm = Quantities.getQuantity (2, METER) .add (Quantities.getQuantity (3, MetricPrefix.KILO (METER))); assertEquals (totalKm.getValue (). intValue (), 3002);

I dette eksempel svarer både meter og kilometer enheder til Længde dimension, så de kan tilføjes. Resultatet udtrykkes i enheden af ​​det første objekt.

6. Konklusion

I denne artikel så vi det Enheder for måling API giver os en bekvem målemodel. Og bortset fra brugen af Antal og Enhed, så vi også, hvor praktisk det er at konvertere en enhed til en anden på en række måder.

For yderligere information kan du altid tjekke projektet her.

Og som altid er hele koden tilgængelig på GitHub.


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