Introduksjon til javax.measure

1. Oversikt

I denne artikkelen introduserer vi Units of Measurement API - som gir en enhetlig måte å representere tiltak og enheter på Java.

Mens vi arbeider med et program som inneholder fysiske mengder, må vi fjerne usikkerheten om enhetene som brukes. Det er viktig at vi administrerer både tallet og dets enhet for å forhindre feil i beregningene.

JSR-363 (tidligere JSR-275 eller javax. mål bibliotek) hjelper oss med å spare utviklingstiden, og samtidig gjør koden mer lesbar.

2. Maven-avhengigheter

La oss bare begynne med Maven-avhengigheten for å trekke i biblioteket:

 javax.measenhet-api 1.0 

Den siste versjonen finner du på Maven Central.

De enhet-api prosjektet inneholder et sett med grensesnitt som definerer hvordan man skal jobbe med mengder og enheter. For eksemplene bruker vi referanseimplementeringen av JSR-363, som er enhet-ri:

 tekniske enheter enhet-ri 1.0.3 

3. Utforske API

La oss se på eksemplet der vi vil lagre vann i en tank.

Den eldre implementeringen vil se slik ut:

offentlig klasse WaterTank {public void setWaterQuantity (dobbel mengde); }

Som vi kan se, nevner ikke ovenstående kode enheten for vannmengde og er ikke egnet for nøyaktige beregninger på grunn av tilstedeværelsen av dobbelt type.

Hvis en utvikler feilaktig overfører verdien med en annen måleenhet enn den vi forventer, kan det føre til alvorlige feil i beregningene. Slike feil er veldig vanskelig å oppdage og løse.

De JSR-363 API gir oss Mengde og Enhet grensesnitt, som løser denne forvirringen og lar denne typen feil være utenfor programmets omfang.

3.1. Enkelt eksempel

La oss nå utforske og se hvordan dette kan være nyttig i eksemplet vårt.

Som nevnt tidligere, JSR-363 inneholder de Mengde grensesnitt som representerer en kvantitativ egenskap som volum eller areal. Biblioteket har en rekke undergrensesnitt som modellerer de mest brukte målbare attributtene. Noen eksempler er: Volum, Lengde, Elektrisk ladning, Energi, Temperatur.

Vi kan definere Mengde objekt, som skal lagre vannmengden i vårt eksempel:

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

Ved siden av Mengde grensesnitt, vi kan også bruke Enhet grensesnitt for å identifisere måleenheten for en eiendom. Definisjoner for ofte brukte enheter finner du i enhet-ri bibliotek, for eksempel: KELVIN, MÅLER, NEWTON, CELSIUS.

Et objekt av typen Mengde har metoder for å hente enheten og verdien: getUnit () og getValue ().

La oss se et eksempel for å sette verdien for mengden vann:

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

Vi kan også konvertere dette Volum i LITER raskt til andre enheter:

dobbelt volumInMilliLitre = vannkapasitet. til (MetricPrefix.MILLI (LITER)). getValue (). doubleValue (); assertEquals (9200.0, volumeInMilliLitre, 0.0f);

Men når vi prøver å konvertere vannmengden til en annen enhet - som ikke er av typen Volum, får vi en kompileringsfeil:

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

3.2. Klasseparameterisering

For å opprettholde dimensjonskonsistensen utnytter rammeverket naturlig generiske stoffer.

Klasser og grensesnitt parametriseres etter mengdetype, noe som gjør det mulig å få kontrollert enhetene våre på kompileringstidspunktet. Kompilatoren vil gi en feil eller advarsel basert på hva den kan identifisere:

Enhetskilometer = MetricPrefix.KILO (METER); Enhetscentimeter = MetricPrefix.CENTI (LITER); // kompileringsfeil

Det er alltid en mulighet for å omgå typekontrollen med asType () metode:

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

Vi kan også bruke et jokertegn hvis vi ikke er sikre på typen mengde:

Enhet kelvinPerSec = KELVIN.divide (SECOND);

4. Enhetskonvertering

Enhets kan hentes fra SystemOfUnits. Referanseimplementeringen av spesifikasjonen inneholder Enheter implementering av grensesnittet som gir et sett med statiske konstanter som representerer de mest brukte enhetene.

I tillegg kan vi også opprette en helt ny tilpasset enhet eller opprette en enhet ved å bruke algebraiske operasjoner på eksisterende enheter.

Fordelen med å bruke en standard enhet er at vi ikke støter på konverteringsgruvene.

Vi kan også bruke prefikser, eller multiplikatorer fra MetricPrefix klasse, som KILO (Enhet) og CENTI (Enhet), som tilsvarer å multiplisere og dele med henholdsvis en kraft på 10.

For eksempel kan vi definere “Kilometer” og “Centimeter” som:

Enhetskilometer = MetricPrefix.KILO (METER); Enhetscentimeter = MetricPrefix.CENTI (METER);

Disse kan brukes når en enhet vi ønsker ikke er tilgjengelig direkte.

4.1. Egendefinerte enheter

I alle fall, hvis en enhet ikke eksisterer i enhetssystemet, kan vi opprette nye enheter med nye symboler:

  • AlternateUnit - en ny enhet med samme dimensjon men forskjellig symbol og natur
  • Produktenhet - en ny enhet opprettet som et produkt av andre enheters rasjonelle krefter

La oss lage noen tilpassede enheter ved hjelp av disse klassene. Et eksempel på AlternateUnit for trykk:

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

Tilsvarende et eksempel på Produktenhet og dens konvertering:

@Test public void givenUnit_whenProduct_ThenGetProductUnit () {Unit squareMetre = METRE.multiply (METER) .asType (Area.class); Mengdelinje = Quantities.getQuantity (2, METER); assertEquals (line.multiply (line) .getUnit (), squareMetre); }

Her har vi opprettet en kvadratmeter sammensatt enhet ved å multiplisere MÅLER med seg selv.

Neste, til enhetstyper, gir rammeverket også en UnitConverter klasse, som hjelper oss med å konvertere en enhet til en annen, eller lage en ny avledet enhet kalt TransformedUnit.

La oss se et eksempel for å slå enheten med en dobbel verdi, fra meter til kilometer:

@Test offentlig ugyldighet givenMeters_whenConvertToKilometer_ThenConverted () {double distanceInMeters = 50.0; UnitConverter metreToKilometre = METRE.getConverterTo (MetricPrefix.KILO (METER)); dobbel distanceInKilometers = metreToKilometre.convert (distanceInMeters); assertEquals (0.05, distanceInKilometers, 0.00f); }

For å lette utvetydig elektronisk kommunikasjon av mengder med enhetene, tilbyr biblioteket Enhetsformat grensesnitt, som forbinder hele etiketten med Enheter.

La oss sjekke etikettene til noen systemenheter ved hjelp av SimpleUnitFormat gjennomføring:

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

5. Utføre operasjoner med mengder

De Mengde grensesnitt inneholder metoder for de vanligste matematiske operasjonene: legge til(), trekke fra(), multiplisere(), dele opp(). Ved hjelp av disse kan vi utføre operasjoner mellom Mengde gjenstander:

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

Metodene bekrefter også Enheter av gjenstandene de opererer på. For eksempel vil prøve å multiplisere meter med liter resultere i en kompileringsfeil:

// kompileringsfeil Mengde totalt = Quantities.getQuantity (2, METER) .add (Quantities.getQuantity (3, LITER));

På den annen side kan to objekter uttrykt i enheter som har samme dimensjon legges til:

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

I dette eksemplet tilsvarer både meter- og kilometerenhetene Lengde dimensjon slik at de kan legges til. Resultatet uttrykkes i enheten til det første objektet.

6. Konklusjon

I denne artikkelen så vi det Enheter for måling API gir oss en praktisk målemodell. Og bortsett fra bruken av Mengde og Enhet, så vi også hvor praktisk det er å konvertere en enhet til en annen, på en rekke måter.

For ytterligere informasjon kan du alltid sjekke ut prosjektet her.

Og som alltid er hele koden tilgjengelig på GitHub.


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