Статьи

Новые методы BigInteger в Java 8

Внимание к новым функциям в  JDK 8 по  праву сфокусировано на новых функциях и синтаксисе языка. Тем не менее, есть несколько приятных дополнений к библиотекам и API, и в этой статье я расскажу о четырех новых методах, добавленных в   класс BigIntegerlongValueExact ()intValueExact ()shortValueExact () и  byteValueExact () .

Все четыре недавно представленных метода «xxxxxExact ()» выдают исключение  ArithmeticException,  если число, содержащееся в  BigInteger экземпляре, не может быть указано в указанной форме (указанной в имени метода) без потери информации.  BigInteger уже были методы  intValue ()  и  longValue (),  а также унаследованные (от Number) методы  shortValue ()  и  byteValue () . Эти методы не генерируют исключения, если BigIntegerЗначение теряет информацию в представлении как один из этих типов. Хотя на первый взгляд это может показаться преимуществом, это означает, что код, использующий результаты этих методов, использует значения, которые не являются точными без какой-либо возможности узнать, что информация была потеряна. Новые методы «xxxxxExact» ArithmenticException скорее бросают , чем делают вид, что дают результат, который потерял значительную информацию.

Следующий простой код листинга демонстрирует «устаревшие» методы , которые представляют неверные данные в типах  byte, shortintи  , long а не бросать исключение. В этом же коде демонстрируется использование новых методов «xxxxxExact», которые выдают исключение при потере информации, а не представляют неверное представление. Выход выполнения этого кода следует код и демонстрирует , как методы ведут себя по- разному , когда  BigInteger содержит значение с большим количеством информации , чем возвращаемый  byteshort, intили  long может представлять.

BigIntegerDem.java

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();
      }
   }
}

Выход

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 BigIntegerinstance. 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.