JAVA基本类型包装类 BigDecimal BigInteger 的使用

目录
  • 1、了解包装类
  • 2、Integer
  • 3、Double
  • 4、BigDecimal
  • 5、BigInteger

1、了解包装类

Java 中预定义了八种基本数据类型,包括:byteintlongdoublefloatbooleancharshort。基本类型与对象类型最大的不同点在于,基本类型基于数值,对象类型基于引用。

例如有一个方法 f() ,它的参数分别是对象类型 和 基本类型:

void f(Object obj){
 //参数引用类型,保存的是内存地址
}

f(123){
 //基本类型
}

基本类型基于数值,所以基本类型是没有类而言的,是不存在类的概念的,也就是说,变量只能存储数值,而不具备操作数据的方法。

对象类型则截然不同,变量实际上是某个类的实例,可以拥有属性方法等信息,不再单一的存储数值,可以提供各种各样对数值的操作方法,但代价就是牺牲一些性能并占用更多的内存空间。

Java 中提供了哪些「包装类型」来弥补「基本类型」不具备面向对象思想的劣势呢?看下图:

java.lang.Number

这里需要提到 java.lang.Number,它是所有数值类的父类,其直接子类包括:ByteShortIntegerLongFloatDoubleBigDecimalBigInteger

这些类取出内部封装的基本类型值的方法很简单也很好记:byteValue()shortValue() intValue() longValue() floatValue() doubleValue()

其他使用方法也基本相同,下面我们以 Integer 和 Double 为例具体讲一讲

2、Integer

首先需要明确一点的是,既然 Integer int 的包装类型,那么必然 Integer 也能像 int 一样存储整型数值。有兴趣的同学可以看看源码。

Integer 类的内部定义了一个私有字段 value,专门用于保存一个整型数值,整个包装类就是围绕着这个 value 封装了各种不同操作的方法:

创建对象

Integer i1 = 21;
Integer i2 = Integer.valueOf("21");

自动拆装箱

所谓「拆箱」就是指,包装类型转换为基本类型的过程,而所谓的「装箱」则是基本类型到包装类型的过程。

Integer integer = new Integer(21);//装箱
int num = integer.intValue();//拆箱

自从 jdk1.5 以后,引入了自动拆装箱的概念,上述代码可以简化成如下代码:

Integer integer = 21;//装箱
int num = integer;//拆箱

我们来进行分析一下。

自动装箱

Integer integer = 21; 给一个 Integer 类型的对象不能直接赋一个基本类型值,integer 保存的是一个内存地址。21 自动封装成一个对象,把这个对象的地址赋值给 integer。这个对象是自动创建的,是自动装箱。在程序中编译成:Integer integer = Integer.valueOf(21);

自动拆箱

int num = integer; 定义一个 int 类型变量,num 应该直接存一个值,integer 保存的是一个内存地址。integer 自动取出对象中的值,然后把值赋值给 num。系统为我们执行了:int num = integer.intValue();

拆装箱是需要方法调用的,耗资源,所以我们的程序中应当尽量避免大量的「拆装箱」操作。

自动拆箱要当心 null 值

我们看以下程序:

public class Main {
    public static void main(String[] args) {
        int j = 0;
        List<Integer> list = new ArrayList<>();
        list.add(3);
        list.add(null);
        for (int i : list) {
            j += i;
        }
        System.out.println(j);
    }
}

运行时会报空指针

所以在获取到值有可能为空要装箱的时候,一定要加上 null 值的校验。所以可以把程序改为:

程序结果为:

3

面试题1

  Integer i1 = 100;
        Integer i2 = 100;
        Integer i3 = 200;
        Integer i4 = 200;

        System.out.println(i1==i2);
        System.out.println(i3==i4);

输出结果:

true
false

Integer 类中,存在 Integer 实例缓存数组,范围:-128 - 127。如果在自动装箱的时候给局部变量的int型值是在上面的范围之中,如果是范围内的值,就使用存在的缓存对象;如果不是范围内的值,会新建对象。

面试题2

  Integer i1 = new Integer(21);
        Integer i2 = new Integer(21);
        System.out.println(i1 == i2);
        System.out.println(i1.equals(i2));

输出结果:

false
true

如果new就会在堆内存开辟空间,new两次就开辟两段空间,两段空间地址值一定不一样。不推荐这么写,过时了。

方法

1、从 Number 继承的 6 个方法

byteValue()shortValue()intValue() longValue()floatValue()doubleValue()

2、字符串解析成 int

Integer.parseInt("255"); //将字符串转换为 int 类型的数值,按十进制解析成 255
Integer.parseInt("11111111", 2) //按二进制解析成 255
Integer.parseInt("377",8); //按八进制解析成 255
Integer.parseInt("ff", 16); //按十六进制解析成 255

3、进制转换

Integer.toBinaryString(255); //将数字转成二进制,解析成"11111111"
Integer.toOctalString(255); //将数字转换成八进制,解析成"377"
Integer.toHexString(255); //将数字转换成十六进制,解析成"ff"

完整程序

  System.out.println("i1:" + Integer.parseInt("255"));
        System.out.println("i2:" + Integer.parseInt("11111111", 2));
        System.out.println("i3:" + Integer.parseInt("377", 8));
        System.out.println("i4:" + Integer.parseInt("ff", 16));

        System.out.println("s1:" + Integer.toBinaryString(255));
        System.out.println("s2:" + Integer.toOctalString(255));
        System.out.println("s3:" + Integer.toHexString(255));

输出结果

255
255
255
255
11111111
377
ff

3、Double

Double 类在对象中包装了一个基本类型 double 的值。Double 类对象包含一个 double 类型的字段。此外,该类还提供了多个方法,可以将 double 类型与 String 类型相互转换,同时 还提供了处理 double 类型时比较常用的常量和方法。

创建对象

Double d1 = 21d;
Double d2 = Double.valueOf("21");

方法

1、从Number类继承的6个方法,同上
2、将数字字符串转换为 Double 数值 Double.parseDouble("3.14");
3、判断浮点数特殊值
Double.isInfinite(double d):如果此对象表示的值是正无穷大或负无穷大,则返回 true;否则返回
Double.isNaN(double d):如果此 Double 值是一个非数字值,则返回 true,否则返回 false

Infinity:无穷大
NaN:not a number

4、BigDecimal

浮点数的运算是不精确的,我们看以下运算

System.out.println(2 - 1.9);
System.out.println(4.35 * 100);

运算结果:

那为什么会出现这种情况呢?

因为不论是 float 还是 double 都是浮点数,而计算机是二进制的,浮点数会失去一定的精确度。究其根本原因是,十进制值通常没有完全相同的二进制表示形式,十进制数的二进制表示形式可能不精确。只能无限接近于那个值。

BigDecimal 的作用就是做精确的浮点运算

构造方法

public BigDecimal(double val)    将double表示形式转换为BigDecimal *不建议使用
public BigDecimal(int val)  将int表示形式转换成BigDecimal
public BigDecimal(String val)  将String表示形式转换成BigDecimal * 推荐使用

参数类型为 double 的构造方法的结果有一定的不可预知性。所以通常情况下不使用。

String 构造方法是完全可预知的:写入 newBigDecimal(“0.1”), 将创建一个 BigDecimal,它正好等于预期的 0.1。因此,比较而言,通常建议优先使用 String 构造方法。

double 必须用作 BigDecimal 的源时,请使用 Double.toString(double) 转成String,再使用 String 构造方法。或使用 BigDecimal 的静态方法 valueOf

举例:使用 double 做构造参数的正确使用

如下程序中 bd1 展示了 参数类型为 double 的构造方法的的不可预知性,db2 展示了 String 的构造方法,bd3、bd4 展示了正确使用 double 做为参数的构造方法。

  BigDecimal bd1 = new BigDecimal(1.9);
        BigDecimal bd2 = new BigDecimal("1.9");
        BigDecimal bd3 = BigDecimal.valueOf(1.9);
        BigDecimal bd4 = new BigDecimal(Double.toString(1.9));

        System.out.println("db1:" + bd1);
        System.out.println("db2:" + bd2);
        System.out.println("db3:" + bd3);
        System.out.println("db4:" + bd4);

运行结果:

方法

add(BigDecimal bd)+
subtract(BigDecimal bd)-
multiply(BigDecimal bd)*
divide(BigDecimal bd)/
divide(BigDecimal bd,
保留位数,舍入方式)
setScale(保留位数,舍入方式) 舍入运算,运算结果会封装成新的大数字对象返回

举例:实现本节开头的精确运算

  BigDecimal bd1 = new BigDecimal("2");
        BigDecimal bd2 = new BigDecimal("1.9");
        System.out.println("2 - 1.9 = " + bd1.subtract(bd2));

        BigDecimal bd3 = new BigDecimal("4.35");
        BigDecimal bd4 = new BigDecimal("100");
        System.out.println("4.35 * 100 = " + bd3.multiply(bd4));

运行结果:

举例:四舍五入

BigDecimal bd = BigDecimal.valueOf(2.345);
double result = bd.setScale(2, RoundingMode.HALF_UP).doubleValue();
System.out.println("result:" + result);

运行结果:

举例:计算降落距离

  System.out.println("输入降落时间");
        double t = new Scanner(System.in).nextDouble();
        //1/2*9.8*t*t
        BigDecimal a = BigDecimal.valueOf(0.5);
        BigDecimal b = BigDecimal.valueOf(9.8);
        BigDecimal c = BigDecimal.valueOf(t);

        double result = a.multiply(b).multiply(c.pow(2)).doubleValue();

        System.out.println("降落距离:" + result + "米");

运行结果:

5、BigInteger

作用:做超大整数运算

在 Java中,由CPU原生提供的整型最大范围是 64 位 long 型整数。使用 long 型整数可以直接通过 CPU 指令进行计算,速度非常快。

如果我们使用的整数范围超过了 long 型怎么办?这个时候,就只能用软件来模拟一个大整数。java.math.BigInteger 就是用来表示任意大小的整数。

我们通过一个例子就可以了解它的使用。

举例:计算阶乘

public class Main {
    public static void main(String[] args) {
        System.out.println("输入数字来计算阶乘:");
        int number = new Scanner(System.in).nextInt();
        System.out.println("阶乘结果:" + f(number));
    }

    private static String f(int number) {
        //超大整数运算
        BigInteger bd = BigInteger.valueOf(number);
        for (int i = number - 1; i >= 1; i--) {
            BigInteger bi = BigInteger.valueOf(i);
            bd = bd.multiply(bi);
        }
        return bd.toString();
    }
}

运行结果:

方法

BigInteger abs()  返回大整数的绝对值
BigInteger add(BigInteger val) 返回两个大整数的和
BigInteger and(BigInteger val)  返回两个大整数的按位与的结果
BigInteger andNot(BigInteger val) 返回两个大整数与非的结果
BigInteger divide(BigInteger val)  返回两个大整数的商
double doubleValue()   返回大整数的double类型的值
float floatValue()   返回大整数的float类型的值
BigInteger gcd(BigInteger val)  返回大整数的最大公约数
int intValue() 返回大整数的整型值
long longValue() 返回大整数的long型值
BigInteger max(BigInteger val) 返回两个大整数的最大者
BigInteger min(BigInteger val) 返回两个大整数的最小者
BigInteger mod(BigInteger val) 用当前大整数对val求模
BigInteger multiply(BigInteger val) 返回两个大整数的积
BigInteger negate() 返回当前大整数的相反数
BigInteger not() 返回当前大整数的非
BigInteger or(BigInteger val) 返回两个大整数的按位或
BigInteger pow(int exponent) 返回当前大整数的exponent次方
BigInteger remainder(BigInteger val) 返回当前大整数除以val的余数
BigInteger leftShift(int n) 将当前大整数左移n位后返回
BigInteger rightShift(int n) 将当前大整数右移n位后返回
BigInteger subtract(BigInteger val)返回两个大整数相减的结果
byte[] toByteArray(BigInteger val)将大整数转换成二进制反码保存在byte数组中
String toString() 将当前大整数转换成十进制的字符串形式
BigInteger xor(BigInteger val) 返回两个大整数的异或

到此这篇关于JAVA基本类型包装类 BigDecimal BigInteger 的使用的文章就介绍到这了,更多相关JAVA BigDecimal、BigInteger 的使用内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 解决Java包装类比较时遇到的问题

    前言 本文主要给大家介绍了关于Java包装类在比较时遇到的一些问题的解决方法,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 例1: Integer a = 1; Integer b = 2; Integer c = 3; Integer d = 3; Integer e= 321; Integer f= 321; Long g = 3L; System.out.println(c == d); //1 System.out.println(e == f); //2 Syste

  • Java包装类原理与用法实例分析

    本文实例讲述了Java包装类原理与用法.分享给大家供大家参考,具体如下: 产生: 为了提高数据类型的的面向对象性,所以产生了包装类,包装类中有各种便利的方法 数据类型对应的包装类 使用: 包装类可以实现将基本类型转换成字符串(或者字符串转换成基本类型): 1.包装类中方法parseXXX 2.构造器 3.对于String,使用String中的valueof能将基本数据类型转换成字符串 包装类的实例可以与基本数据类型比较: 直接把实例中包装的数值拿出来比较 当如果是包装类实例的比较的话,比较的是所

  • Java包装类的缓存机制原理实例详解

    这篇文章主要介绍了Java包装类的缓存机制原理实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 java 包装类的缓存机制,是在Java 5中引入的一个有助于节省内存.提高性能的功能,只有在自动装箱时有效 Integer包装类 举个栗子: Integer a = 127; Integer b = 127; System.out.println(a == b); 这段代码输出的结果为true 使用自动装箱将基本类型转为封装类对象这个过程其实

  • 浅谈Java包装类型Long的==操作引发的低级bug

    目录 背景 两个 Long  类型的  == 对 Collections.EMPTY_SET 进行 add 引发的异常 Collections 的空集合使用注意事项 启示录 背景 一个简单的列表检索功能,列表元素有一个 Long 类型的属性,遍历过程中犯了一个低级错误,导致功能流程始终错误,本文将分享两个低级错误引发的 bug. 两个 Long  类型的  == 查找某个元素 A 在列表 B 中对应的对象的时候,根据元素主键查询,主键类型为包装类型 Long ,遍历流程如下: for(MyDat

  • Java包装类之自动装箱与拆箱

    JDK 5.0之前 基本数据类型<---->包装类:调用包装类的构造器(代码里有知识点和注意点) 转换目的:有了类的特点,就可以调用类中的方法 public class WrapperTest { // 基本数据类型--->包装类:调用包装类的构造器 @Test public void test1() { int num1 = 10; Integer in1 = new Integer(num1); System.out.println(in1.toString());//10 Inte

  • 详解Java包装类及自动装箱拆箱

    Java包装类 基本类型 大小 包装器类型 boolean / Boolean char 16bit Boolean byte 8bit Byte short /16bit Short int 32bit Integer long 64bit Long float 32bit Float double 64bit Double void / Void Java 的包装类有两个主要的目的: Java包装类将基本数据类型的值"包装"到对象中,对基本数据类型的操作变为了对对象进行操作,从而使

  • JAVA包装类及自动封包解包实例代码

    复制代码 代码如下: public class Wrapper {     public static void main(String[] args) {         int i = 500;         Integer t = new Integer(i);         int j = t.intValue();         String s = t.toString();         System.out.println(t);         Integer t1 =

  • JAVA基本类型包装类 BigDecimal BigInteger 的使用

    目录 1.了解包装类 2.Integer 3.Double 4.BigDecimal 5.BigInteger 1.了解包装类 Java 中预定义了八种基本数据类型,包括:byte,int,long,double,float,boolean,char,short.基本类型与对象类型最大的不同点在于,基本类型基于数值,对象类型基于引用. 例如有一个方法 f() ,它的参数分别是对象类型 和 基本类型: void f(Object obj){ //参数引用类型,保存的是内存地址 } f(123){

  • Java基本类型包装类概述与Integer类、Character类用法分析

    本文实例讲述了Java基本类型包装类概述与Integer类.Character类用法.分享给大家供大家参考,具体如下: 基本类型包装类概述 将基本数据类型封装成对象的好处在于可以在对象中定义更多的功能方法操作该数据. 常用的操作之一:用于基本数据类型与字符串之间的转换. 基本类型和包装类的对应 Byte,Short,Integer,Long,Float,Double,Character,Boolean Integer类 为了让基本类型的数据进行更多的操作,Java就为每种基本类型提供了对应的包装

  • Java 包装类型及易错陷阱详解

    目录 一.预备知识 1.1 Java内存管理 1.2 基本数据类型的包装类 1.3 包装类的构造方法 1.4 包装类的优缺点 1.5 包装类易错点 二.自动拆/装箱 三.整形池 四.优先选择基本数据类型 一.预备知识 1.Java把内存划分成两种:一种是栈内存,另一种是堆内存. 2.int是基本类型,直接存数值:而 Integer是类,产生对象时用一个引用指向这个对象. 3.包装器(wrapper)--这是<JAVA核心技术>一书中对Integer这类对象的称呼. 4.包装器位于java.la

  • 浅谈Java基础知识之BigDecimal

    一.基本使用 使用示例: // 初始化 BigDecimal bd1=new BigDecimal("456"); BigDecimal bd2=new BigDecimal("123"); // 加 BigDecimal add=bd1.add(bd2); // 减 BigDecimal subtract=bd1.subtract(bd2); // 乘 BigDecimal multiply=bd1.multiply(bd2); // 除 BigDecimal d

  • Java学习笔记:关于Java double类型相加问题

    目录 Java double类型相加问题 一.这个时候就要采用BigDecimal函数进行运算 二.double 三种加法比较 Java Double类详解 Double 类的构造方法 Double 类的常用方法 Double 类的常用常量 Java double类型相加问题 多个double类型的数直接相加的时候,可能存在精度误差.( 由于计算机算法以及硬件环境决定只能识别 0 1.计算机默认的计算结果在都在一个指定精度范围之内,想往深的了解,可以学习数值分析等) 在金融方面是绝对不允许的,好

  • java double类型相加精度问题的解决

    我就废话不多说了,大家还是直接看代码吧~ package com.hxyl.action; import java.text.DecimalFormat; public class Test { public static void main(String[] args) { // DecimalFormat 类主要靠 # 和 0 两种占位符号来指定数字长度.0 表示如果位数不足则以 0 填充,# 会把最后面的零默认省略. DecimalFormat df = new DecimalFormat

  • java各种类型对象占用内存情况分析

    前言 其实一般的程序猿根本不用了解这么深,只有当你到了一定层次,需要了解jvm内部运行机制,或者高并发多线程下,你写的代码对内存有影响,你想做性能优化.等等等等,一句话,当你想深入了解java对象在内存中,如何存储,或者每个对象占用多大空间时,你会感谢这篇文章 本文主要分析jvm中的情况,实验环境为64位window10系统.JDK1.8,使用JProfiler进行结论验证 很多描述以及 概念是基于你懂基本java知识的,如果你看起来有点吃力,要加油咯 本片更偏重验证,更多理论,请参考:http

  • Java基础之包装类

    一.java的包装类 什么是包装类 对于基本数据类型来讲,其实就是一个数字,但是当给基本数据类型添加一些属性 方法和构造器,将基本数据类型对应进行一个封装,就产生了一个新的类,这个类被称为是包装类. 那么基本数据类型在前面中讲过有byte short int long float double char boolean,也就是将这些进行封装,基本数据类型和包装类的对应关系是怎样的呢? 基本数据类型 对应的包装类 byte Byte short Short int Integer long Lon

  • 详细总结Java基础类和包装类

    一.简介 当需要往ArrayList,HashMap中放东西时,像int,double这种基本类型是放不进去的,因为容器都是装object的,这是就需要这些基本类型的包装器类了. 基本数据类型存放在栈中,效率更高 每个基本类型在java.lang包中都有一个相应的包装类,new出来的对象存在于堆中(通过栈中的引用来使用这些对象),是一个对象,因此具有更多的诸如"转换"的方法 例子: 1.int转Integer int i = 0; Integer ii = new Integer(i)

  • java基础之包装类的介绍及使用

    1. 包装类的介绍 针对八种基本数据类型定义相应的引用类型--包装类(封装类),有了类的热点后,就可以调用类中的方法 2. 基本数据类型 --> 包装类:调用包装类的构造器,如in1.toString() 使用场景:如果形参是一个object类类型的,必须要把基本类型转换成包装类才能传入到形参用 3. 包装类 --> 基本数据类型:调用包装类的xxxValue() 使用场景:包装类作为一个对象,不能做加减乘除运算的,必须转换成基本类型后才可以 但jdk5已经支持自动装箱和自动拆箱,所以不需要再

随机推荐