Mam metodę Hibernate, która zwraca mi BigDecimal. Mam inną metodę API, do której muszę przekazać ten numer, ale akceptuje ona liczbę całkowitą jako parametr. Nie mogę zmienić typów zwracanych ani typów zmiennych obu metod.
Teraz jak przekonwertować BigDecimal na Integer i przekazać go do drugiej metody?
Czy jest wyjście z tego?
java
integer
casting
bigdecimal
Vishal
źródło
źródło
Odpowiedzi:
Zadzwoniłbyś
myBigDecimal.intValueExact()
(lub po prostuintValue()
), a nawet wyrzuci wyjątek, jeśli stracisz informacje. To zwraca int, ale zajmuje się tym autoboxing.źródło
intValueExact()
to dobra rekomendacja; został dodany w 1.5intValue()
jest niebezpieczne, chyba że stawiasz na 100% swoje życie, mając pewność, że numer mieści się wInteger
zakresie.Czy możesz zagwarantować, że
BigDecimal
nigdy nie będzie zawierał wartości większej niżInteger.MAX_VALUE
?Jeśli tak, to dzwoni tutaj kod
intValue
:źródło
TL; DR
Użyj jednego z nich dla potrzeb powszechnej konwersji
//Java 7 or below bigDecimal.setScale(0, RoundingMode.DOWN).intValueExact() //Java 8 bigDecimal.toBigInteger().intValueExact()
Rozumowanie
Odpowiedź zależy od wymagań i od tego, jak odpowiesz na to pytanie.
BigDecimal
potencjalnie będzie miał niezerową część ułamkową?BigDecimal
potencjalnie nie będzie pasować doInteger
zakresu?Jeśli odpowiedziałeś nie na pierwsze 2 pytania, możesz po prostu użyć
BigDecimal.intValueExact()
tego, co sugerowali inni i pozwolić, aby wybuchło, gdy wydarzy się coś nieoczekiwanego.Jeśli nie masz 100% pewności co do pytania numer 2, zawsze
intValue()
jest to zła odpowiedź.Robię to lepiej
Skorzystajmy z następujących założeń na podstawie innych odpowiedzi.
intValueExact()
auto-boksBigDecimal
jest większy niżInteger
zakres, ponieważ wszystko inne byłoby szalone, chyba że masz bardzo konkretną potrzebę zawijania, co dzieje się, gdy upuszczasz bity o wyższym porządku.Biorąc pod uwagę te parametry,
intValueExact()
zgłasza wyjątek, gdy nie chcemy, aby nasza część ułamkowa była różna od zera. Z drugiej stronyintValue()
nie zgłasza wyjątku, gdy powinien, jeśli naszBigDecimal
jest zbyt duży.Aby uzyskać to, co najlepsze z obu światów, zaokrąglij
BigDecimal
pierwszy, a następnie przekonwertuj. Ma to również tę zaletę, że zapewnia większą kontrolę nad procesem zaokrąglania.Spock Groovy Test
void 'test BigDecimal rounding'() { given: BigDecimal decimal = new BigDecimal(Integer.MAX_VALUE - 1.99) BigDecimal hugeDecimal = new BigDecimal(Integer.MAX_VALUE + 1.99) BigDecimal reallyHuge = new BigDecimal("10000000000000000000000000000000000000000000000") String decimalAsBigIntString = decimal.toBigInteger().toString() String hugeDecimalAsBigIntString = hugeDecimal.toBigInteger().toString() String reallyHugeAsBigIntString = reallyHuge.toBigInteger().toString() expect: 'decimals that can be truncated within Integer range to do so without exception' //GOOD: Truncates without exception '' + decimal.intValue() == decimalAsBigIntString //BAD: Throws ArithmeticException 'Non-zero decimal digits' because we lose information // decimal.intValueExact() == decimalAsBigIntString //GOOD: Truncates without exception '' + decimal.setScale(0, RoundingMode.DOWN).intValueExact() == decimalAsBigIntString and: 'truncated decimal that cannot be truncated within Integer range throw conversionOverflow exception' //BAD: hugeDecimal.intValue() is -2147483648 instead of 2147483648 //'' + hugeDecimal.intValue() == hugeDecimalAsBigIntString //BAD: Throws ArithmeticException 'Non-zero decimal digits' because we lose information //'' + hugeDecimal.intValueExact() == hugeDecimalAsBigIntString //GOOD: Throws conversionOverflow ArithmeticException because to large //'' + hugeDecimal.setScale(0, RoundingMode.DOWN).intValueExact() == hugeDecimalAsBigIntString and: 'truncated decimal that cannot be truncated within Integer range throw conversionOverflow exception' //BAD: hugeDecimal.intValue() is 0 //'' + reallyHuge.intValue() == reallyHugeAsBigIntString //GOOD: Throws conversionOverflow ArithmeticException because to large //'' + reallyHuge.intValueExact() == reallyHugeAsBigIntString //GOOD: Throws conversionOverflow ArithmeticException because to large //'' + reallyHuge.setScale(0, RoundingMode.DOWN).intValueExact() == reallyHugeAsBigIntString and: 'if using Java 8, BigInteger has intValueExact() just like BigDecimal' //decimal.toBigInteger().intValueExact() == decimal.setScale(0, RoundingMode.DOWN).intValueExact() }
źródło
Cóż, możesz zadzwonić
BigDecimal.intValue()
:Następnie możesz jawnie wywołać
Integer.valueOf(int)
lub pozwolić automatycznemu boksowaniu zrobić to za Ciebie, jeśli używasz wystarczająco aktualnej wersji Javy.źródło
Poniższe powinno załatwić sprawę:
BigDecimal d = new BigDecimal(10); int i = d.intValue();
źródło
Czy próbowałeś wywołać BigInteger # intValue () ?
źródło
Zobacz BigDecimal # intValue ()
źródło
Okazało się, że powyższe nie działa dla mnie. Wyciągałem wartość komórki z tabeli JTable, ale nie mogłem rzutować na wartość double lub int itp. Moje rozwiązanie:
Object obj = getTable().getValueAt(row, 0);
gdzie wiersz 0 zawsze byłby liczbą. Mam nadzieję, że to pomoże każdemu, kto nadal przewija!
źródło