כסף של Java ו- API של מטבע
1. סקירה כללית
JSR 354 - "מטבע וכסף" עוסק בתקינה של מטבעות וסכומים כספיים בג'אווה.
מטרתו היא להוסיף API גמיש ומתרחב למערכת האקולוגית של Java ולהפוך את העבודה עם סכומים כספיים לפשוטה ובטוחה יותר.
ה- JSR לא עשה את דרכו ל- JDK 9 אך הוא מועמד לשחרור JDK בעתיד.
2. התקנה
ראשית, בואו נגדיר את התלות שלנו pom.xml קוֹבֶץ:
org.javamoney moneta 1.1
ניתן לבדוק כאן את הגרסה האחרונה של התלות.
3. תכונות JSR-354
המטרות של ממשק ה- API "מטבע וכסף":
- לספק ממשק API לטיפול וחישוב סכומים כספיים
- להגדרת מחלקות המייצגות מטבעות וסכומים כספיים, כמו גם עיגול כספי
- כדי להתמודד עם שערי מטבע
- להתמודדות עם עיצוב וניתוח מטבעות וסכומים כספיים
4. דגם
המחלקות העיקריות במפרט JSR-354 מתוארות בתרשים הבא:
המודל מחזיק בשני ממשקים עיקריים יחידת מטבע ו כמות כספית, מוסבר בסעיפים הבאים.
5. יחידת מטבע
יחידת מטבע מעצב את המאפיינים המינימליים של מטבע. את המקרים שלה ניתן להשיג באמצעות Monetary.getCurrency שיטה:
@Test הציבור בטל givenCurrencyCode_whenString_thanExist () {CurrencyUnit usd = Monetary.getCurrency ("USD"); assertNotNull (usd); assertEquals (usd.getCurrencyCode (), "USD"); assertEquals (usd.getNumericCode (), 840); assertEquals (usd.getDefaultFractionDigits (), 2); }
אנחנו יוצרים יחידת מטבע באמצעות א חוּט ייצוג המטבע, זה יכול להוביל למצב בו אנו מנסים ליצור מטבע עם קוד לא קיים. יצירת מטבעות עם קודים לא קיימים מעלה מטבע לא ידוע יוצא מן הכלל:
@Test (צפוי = UnknownCurrencyException.class) חלל ציבורי givenCurrencyCode_whenNoExist_thanThrowsError () {Monetary.getCurrency ("AAA"); }
6. MonetaryMount
MonetaryMount הוא ייצוג מספרי של סכום כספי. זה תמיד קשור ל יחידת מטבע ומגדיר ייצוג כספי של מטבע.
ניתן ליישם את הסכום בדרכים שונות תוך התמקדות בהתנהגות דרישות ייצוג כספי, המוגדרות על ידי כל מקרי שימוש קונקרטיים. לדוגמה. כֶּסֶף ו FastMoney הם יישומים של MonetaryMount מִמְשָׁק.
FastMoney מכשירים MonetaryMount באמצעות ארוך כייצוג מספרי, והוא מהיר יותר מ- BigDecimal במחיר הדיוק; ניתן להשתמש בו כאשר אנו זקוקים לביצועים ודיוק אינו נושא.
ניתן ליצור מופע כללי באמצעות מפעל ברירת מחדל. בואו נראה את הדרך השונה להשיג MonetaryMount מקרים:
@ מבחן ציבורי בטל givenAmounts_whenStringified_thanEquals () {CurrencyUnit usd = Monetary.getCurrency ("USD"); MonetaryAmount fstAmtUSD = Monetary.getDefaultAmountFactory () .setCurrency (usd) .setNumber (200) .create (); Money moneyof = Money.of (12, usd); FastMoney fastmoneyof = FastMoney.of (2, usd); assertEquals ("USD", usd.toString ()); assertEquals ("200 דולר ארה"ב", fstAmtUSD.toString ()); assertEquals ("12 דולר ארה"ב, moneyof.toString ()); assertEquals ("2.00000 דולר ארה"ב", fastmoneyof.toString ()); }
7. חשבון מוניטרי
אנו יכולים לבצע חשבון כספי בין כֶּסֶף ו FastMoney אך עלינו להיות זהירים כאשר אנו משלבים מקרים של שני המעמדות הללו.
לדוגמא, כאשר אנו משווים מופע אחד של יורו FastMoney עם מופע אירו אחד של כֶּסֶף התוצאה היא שהם אינם זהים:
@ מבחן בטל פומבי שניתן Currency_whenCompared_thanNotequal () {MonetaryAmount oneDolar = Monetary.getDefaultAmountFactory () .setCurrency ("USD"). SetNumber (1) .create (); כסף oneEuro = Money.of (1, "EUR"); assertFalse (oneEuro.equals (FastMoney.of (1, "EUR"))); assertTrue (oneDolar.equals (Money.of (1, "דולר")); }
אנו יכולים לבצע פעולות הוספה, חיסור, הכפל, חלוקה ופעולות חשבון כספיות אחרות בשיטות המסופקות על ידי MonetaryMount מעמד.
פעולות חשבון צריכות לזרוק חישוב חשבון, אם פעולות החשבון בין הסכומים עולות על יכולות סוג הייצוג המספרי המשמש, למשל, אם ננסה לחלק אחת לשלוש, נקבל חישוב חשבון מכיוון שהתוצאה היא מספר אינסופי:
@Test (צפוי = ArithmeticException.class) חלל ציבורי givenAmount_whenDivided_thanThrowsException () {MonetaryAmount oneDolar = Monetary.getDefaultAmountFactory () .setCurrency ("USD"). SetNumber (1) .create (); oneDolar.divide (3); }
בעת הוספה או חיסור של סכומים, עדיף להשתמש בפרמטרים שהם מקרים של MonetaryMount, שכן עלינו להבטיח כי לשני הסכומים יהיה אותו מטבע לביצוע פעולות בין הסכומים.
7.1. חישוב סכומים
ניתן לחשב סך של סכומים במספר דרכים, דרך אחת היא פשוט לשרשר את הסכומים עם:
@Test ציבורי בטל givenAmounts_whenSummed_thanCorrect () {MonetaryAmount [] monetaryAmounts = MonetaryAmount חדש [] {Money.of (100, "CHF"), Money.of (10.20, "CHF"), Money.of (1.15, "CHF") }; SumAmtCHF = Money.of (0, "CHF"); עבור (MonetaryAmount monetaryAmount: monetaryAmounts) {sumAmtCHF = sumAmtCHF.add (monetaryAmount); } assertEquals ("CHF 111.35", sumAmtCHF.toString ()); }
ניתן להשתמש בשרשור על חיסור:
כסף calcAmtUSD = Money.of (1, "USD"). חיסור (fstAmtUSD);
מכפיל:
MonetaryAmount multiplyAmount = oneDolar.multiply (0.25);
או חלוקה:
MonetaryAmount divideAmount = oneDolar.divide (0.25);
בואו נשווה את תוצאות החשבון שלנו באמצעות מיתרים, בהתחשב בכך עם מיתרים מכיוון שהתוצאה מכילה גם את המטבע:
@Test הציבור בטל givenArithmetic_whenStringified_thanEqualsAmount () {CurrencyUnit usd = Monetary.getCurrency ("USD"); Money moneyof = Money.of (12, usd); MonetaryAmount fstAmtUSD = Monetary.getDefaultAmountFactory () .setCurrency (usd) .setNumber (200.50) .create (); MonetaryAmount oneDolar = Monetary.getDefaultAmountFactory () .setCurrency ("USD"). SetNumber (1) .create (); Money subtractedAmount = Money.of (1, "USD"). להפחית (fstAmtUSD); MonetaryAmount multiplyAmount = oneDolar.multiply (0.25); MonetaryAmount divideAmount = oneDolar.divide (0.25); assertEquals ("USD", usd.toString ()); assertEquals ("USD 1", oneDolar.toString ()); assertEquals ("200.5 דולר ארה"ב", fstAmtUSD.toString ()); assertEquals ("12 דולר ארה"ב, moneyof.toString ()); assertEquals ("-199.5 דולר", מופחתAmount.toString ()); assertEquals ("0.25 דולר", multiplyAmount.toString ()); assertEquals ("4 דולר", divideAmount.toString ()); }
8. עיגול מוניטרי
עיגול כספי אינו אלא המרה מסכום עם דיוק לא קבוע לכמות מעוגלת.
נשתמש ב- getDefaultRounding ממשק API המסופק על ידי כַּספִּי בכיתה כדי לבצע את ההמרה. ערכי ברירת המחדל של עיגול מסופקים על ידי המטבע:
@Test ציבורי בטל givenAmount_whenRounded_thanEquals () {MonetaryAmount fstAmtEUR = Monetary.getDefaultAmountFactory () .setCurrency ("EUR"). SetNumber (1.30473908) .create (); MonetaryAmount roundEUR = fstAmtEUR.with (Monetary.getDefaultRounding ()); assertEquals ("1.30473908 אירו", fstAmtEUR.toString ()); assertEquals ("EUR 1.3", roundEUR.toString ()); }
9. המרת מטבע
המרת מטבעות היא היבט חשוב בהתמודדות עם כסף. למרבה הצער, להמרות אלה יש מגוון גדול של יישומים ומקרי שימוש שונים.
ה- API מתמקד בהיבטים הנפוצים של המרת מטבע בהתבסס על המקור, מטבע היעד ושער החליפין.
ניתן לבצע פרמטריה של המרת מטבע או גישה לשערי חליפין:
@Test הציבור בטל givenAmount_whenConversion_thenNotNull () {MonetaryAmount oneDollar = Monetary.getDefaultAmountFactory (). SetCurrency ("USD") .setNumber (1) .create (); CurrencyConversion conversionEUR = MonetaryConversions.getConversion ("EUR"); MonetaryAmount convertAmountUSDtoEUR = oneDollar.with (conversionEUR); assertEquals ("1 דולר ארה"ב, oneDollar.toString ()); assertNotNull (convertAmountUSDtoEUR); }
המרה תמיד מחויבת למטבע. MonetaryMount פשוט ניתן להמיר על ידי העברת a המרת מטבע לסכום עם שיטה.
10. עיצוב מטבע
העיצוב מאפשר גישה לפורמטים על בסיס java.util.Locale. בניגוד ל- JDK, המעצבים המוגדרים על ידי API זה הם בטוחים בברגה:
@ מבחן ציבורי בטל givenLocale_whenFormatted_thanEquals () {MonetaryAmount oneDollar = Monetary.getDefaultAmountFactory () .setCurrency ("USD"). SetNumber (1) .create (); MonetaryAmountFormat formatUSD = MonetaryFormats.getAmountFormat (Locale.US); מחרוזת usFormatted = formatUSD.format (oneDollar); assertEquals ("1 דולר", oneDollar.toString ()); assertNotNull (formatUSD); assertEquals ("USD1.00", usFormatted); }
כאן אנו משתמשים בפורמט המוגדר מראש ויוצרים פורמט מותאם אישית עבור המטבעות שלנו. השימוש בפורמט הסטנדרטי הוא פשוט באמצעות פורמט השיטה של ה- פורמטים כספיים מעמד. הגדרנו את הגדרת הפורמט המותאם אישית שלנו את מאפיין התבנית של בונה שאילתות הפורמט.
כמו בעבר מכיוון שהמטבע נכלל בתוצאה אנו בודקים את התוצאות שלנו באמצעות מיתרים:
@Test הציבור בטל givenAmount_whenCustomFormat_thanEquals () {MonetaryAmount oneDollar = Monetary.getDefaultAmountFactory () .setCurrency ("USD"). SetNumber (1) .create (); MonetaryAmountFormat customFormat = MonetaryFormats.getAmountFormat (AmountFormatQueryBuilder. Of (Locale.US) .set (CurrencyStyle.NAME). Set ("תבנית", "00000.00 ¤"). Build ()); מחרוזת customFormatted = customFormat.format (oneDollar); assertNotNull (customFormat); assertEquals ("1 דולר ארה"ב, oneDollar.toString ()); assertEquals ("00001.00 דולר ארה"ב", פורמט מותאם אישית); }
11. סיכום
במאמר מהיר זה סקרנו את היסודות של JSR Money & Currency Money.
נעשה שימוש בערכים כספיים בכל מקום, וג'אווה מספקת מתחיל לתמוך ולטפל בערכים כספיים, חשבון או המרת מטבע.
כמו תמיד, תוכל למצוא את הקוד מהמאמר ב- Github.