New BigInteger Methods in Java 8
Attention to new features in JDK 8 has rightfully been largely focused on new language features and syntax. However, there are some nice additions to the libraries and APIs and in this post I cover four new methods added to the BigInteger class: longValueExact(), intValueExact(), shortValueExact(), and byteValueExact().
All four of the newly introduced “xxxxxExact()” methods throw an ArithmeticException if the number contained in the BigInteger
instance cannot be provided in the specified form (specified in the method’s name) without loss of information. BigInteger
already had methods intValue() and longValue() as well as inherited (from Number) methods shortValue() and byteValue(). These methods do not throw exceptions if the BigInteger
value loses information in the presentation as one of these types. Although at first glance this may seem like an advantage, it means that code that uses the results of these methods uses values that are not accurate without any ability to know that information was lost. The new “xxxxxExact” methods throw an ArithmenticException
rather than pretending to provide a result that has lost significant information.
The following simple code listing demonstrates the “legacy” methods that present wrong data in types byte
, short
, int
, and long
rather than throwing an exception. The same code also demonstrates use of the new “xxxxxExact” methods that throw an exception when information is lost rather than presenting a bad representation. The output of running this code follows the code and demonstrates how the methods behave differently when the BigInteger
contains a value with more information than the returned byte
, short
, int
, or long
can represent.
BigIntegerDem.java
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 | package dustin.examples.jdk8; import static java.lang.System.out; import java.math.BigInteger; /** * Demonstrate the four new methods of BigInteger introduced with JDK 8. * * @author Dustin */ public class BigIntegerDemo { /** * Demonstrate BigInteger.byteValueExact(). */ private static void demonstrateBigIntegerByteValueExact() { final BigInteger byteMax = new BigInteger(String.valueOf(Byte.MAX_VALUE)); out.println( "Byte Max: " + byteMax.byteValue()); out.println( "Byte Max: " + byteMax.byteValueExact()); final BigInteger bytePlus = byteMax.add(BigInteger.ONE); out.println( "Byte Max + 1: " + bytePlus.byteValue()); out.println( "Byte Max + 1: " + bytePlus.byteValueExact()); } /** * Demonstrate BigInteger.shortValueExact(). */ private static void demonstrateBigIntegerShortValueExact() { final BigInteger shortMax = new BigInteger(String.valueOf(Short.MAX_VALUE)); out.println( "Short Max: " + shortMax.shortValue()); out.println( "Short Max: " + shortMax.shortValueExact()); final BigInteger shortPlus = shortMax.add(BigInteger.ONE); out.println( "Short Max + 1: " + shortPlus.shortValue()); out.println( "Short Max + 1: " + shortPlus.shortValueExact()); } /** * Demonstrate BigInteger.intValueExact(). */ private static void demonstrateBigIntegerIntValueExact() { final BigInteger intMax = new BigInteger(String.valueOf(Integer.MAX_VALUE)); out.println( "Int Max: " + intMax.intValue()); out.println( "Int Max: " + intMax.intValueExact()); final BigInteger intPlus = intMax.add(BigInteger.ONE); out.println( "Int Max + 1: " + intPlus.intValue()); out.println( "Int Max + 1: " + intPlus.intValueExact()); } /** * Demonstrate BigInteger.longValueExact(). */ private static void demonstrateBigIntegerLongValueExact() { final BigInteger longMax = new BigInteger(String.valueOf(Long.MAX_VALUE)); out.println( "Long Max: " + longMax.longValue()); out.println( "Long Max: " + longMax.longValueExact()); final BigInteger longPlus = longMax.add(BigInteger.ONE); out.println( "Long Max + 1: " + longPlus.longValue()); out.println( "Long Max + 1: " + longPlus.longValueExact()); } /** * Demonstrate BigInteger's four new methods added with JDK 8. * * @param arguments Command line arguments. */ public static void main( final String[] arguments) { System.setErr(out); // exception stack traces to go to standard output try { demonstrateBigIntegerByteValueExact(); } catch (Exception exception) { exception.printStackTrace(); } try { demonstrateBigIntegerShortValueExact(); } catch (Exception exception) { exception.printStackTrace(); } try { demonstrateBigIntegerIntValueExact(); } catch (Exception exception) { exception.printStackTrace(); } try { demonstrateBigIntegerLongValueExact(); } catch (Exception exception) { exception.printStackTrace(); } } } |
The Output
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | Byte Max: 127 Byte Max: 127 Byte Max + 1 : - 128 java.lang.ArithmeticException: BigInteger out of byte range at java.math.BigInteger.byteValueExact(BigInteger.java: 4428 ) at dustin.examples.jdk8.BigIntegerDemo.demonstrateBigIntegerByteValueExact(BigIntegerDemo.java: 23 ) at dustin.examples.jdk8.BigIntegerDemo.main(BigIntegerDemo.java: 75 ) Short Max: 32767 Short Max: 32767 Short Max + 1 : - 32768 java.lang.ArithmeticException: BigInteger out of short range at java.math.BigInteger.shortValueExact(BigInteger.java: 4407 ) at dustin.examples.jdk8.BigIntegerDemo.demonstrateBigIntegerShortValueExact(BigIntegerDemo.java: 36 ) at dustin.examples.jdk8.BigIntegerDemo.main(BigIntegerDemo.java: 84 ) Int Max: 2147483647 Int Max: 2147483647 Int Max + 1 : - 2147483648 java.lang.ArithmeticException: BigInteger out of int range at java.math.BigInteger.intValueExact(BigInteger.java: 4386 ) at dustin.examples.jdk8.BigIntegerDemo.demonstrateBigIntegerIntValueExact(BigIntegerDemo.java: 49 ) at dustin.examples.jdk8.BigIntegerDemo.main(BigIntegerDemo.java: 93 ) Long Max: 9223372036854775807 Long Max: 9223372036854775807 Long Max + 1 : - 9223372036854775808 java.lang.ArithmeticException: BigInteger out of long range at java.math.BigInteger.longValueExact(BigInteger.java: 4367 ) at dustin.examples.jdk8.BigIntegerDemo.demonstrateBigIntegerLongValueExact(BigIntegerDemo.java: 62 ) at dustin.examples.jdk8.BigIntegerDemo.main(BigIntegerDemo.java: 102 ) |
As the above output demonstrates, the new BigInteger methods with “xxxxxExact” in their name will not present inaccurate representations when the returned type cannot hold the information in BigInteger
instance. Although exceptions are generally not one of our favorite things, they are almost always going to be better than getting and using wrong data and not even realizing it is wrong.
Reference: | New BigInteger Methods in Java 8 from our JCG partner Dustin Marx at the Inspired by Actual Events blog. |