java中的数据类型

本文详细介绍了Java中的基本数据类型,包括整型、浮点型、字符型和布尔型,分析了它们的取值范围、存储方式以及可能产生的不准确性。此外,还探讨了引用数据类型的特点,如内存指向、数据比较和参数传递方式。同时,讨论了类型转换,包括自动类型转换和强制类型转换,以及基本数据类型与其包装类之间的转换。最后,讲解了Java中浮点型取值范围大于长整型的原因,即浮点型遵循的IEEE754标准。
摘要由CSDN通过智能技术生成

目录

基本数据类型

整型取值范围为何负数比正数多1

布尔型为什么没有指定存储大小

浮点的取值范围为何比long还要大

浮点型的有效位数怎么来的

为什么说浮点型计算往往不准确

引用数据类型

基本数据类型和引用数据类型的区别

1、内存空间指向

 2、判断数据是否相等

3、参数传递方式

类型之间的转换

自动类型转换

强制类型转换

基本数据类型及其包装类的转换


java中变量是最基本的存储单元,要创建变量时,需要指定类型并可为其赋值。语法如下:

type variable = value;

其中type是 Java 类型之一(例如int或String),variable是变量名(例如age或name)。
创建变量就是申请内存来存储值。也就是说创建变量的时候,需要根据变量类型在内存中申请空间,申请的空间只能储存该类型的数据。
数据类型可以划分两大类:基本数据类型(内置数据类型)和引用数据类型 。简单理解的话,所有非基本数据类型的数据类型都是引用类型。

基本数据类型

java语言一共提供了8种基本类型( primitive type ),其中 4 种整型(注意是:带符号的以二进制补码表示的整数)、2 种浮点类型(符合IEEE 754标准的浮点数)、 1 种用于表示 Unicode 编码的字符单元的字符类型 char 和 1 种用于表示真值的 boolean 类型。

类型

分类

字节长度

封装类

取值范围

byte 

整型

1

Byte

 -128(-2^7)~ 127(2^7-1)

short

整型

2

Short

32768(-2^15)~ 32767(2^15 - 1)

int

整型

4

Integer

(-2^31)~ (2^31-1)

long

整型

8

Long

(-2^63)~ (2^63-1)

float

浮点型

4

Float

-3.4E38~3.4E38

double

浮点型

8

Double

-1.7E308~1.7E308

char

字符型

2

Character

\u0000(0)~  \uffff(65,535)

boolean

布尔型

-

Boolean

true,false

对于数值类型的取值范围无需强行记忆,因为对应的包装类都以常量的形式定义了。下面是示例和运行结果例子:

System.out.println("基本类型:int 位数:" + Integer.SIZE);  
System.out.println("最小值:" + Integer.MIN_VALUE);  
System.out.println("最大值:" + Integer.MAX_VALUE);  

了解了基本数据类型的分类概念后,我们重点关注以下几个比较不好理解的问题:

整型取值范围为何负数比正数多1

以byte(1字节8位)为例最高位为符号,0值有2种表达方式:

0000 0000【正零】

1000 0000【负零】

从而出现浪费,于是在存储上约定当符号位位0时表示0,符号位1的用来表示另一个数,取反0111 1111 补码 1000 0000计算值是128,因符号位为负所以得出-128。

布尔型为什么没有指定存储大小

以下四种理解方式:

1、1个bit(位):boolean类型的值只有true和false两种逻辑值,在编译后会使用1和0来表示仅需1位(bit)即可存储,位是计算机最小的存储单位。

2、1个字节:虽然编译后1和0只需占用1位空间,但计算机处理数据的最小单位是1个字节8位,实际存储的空间是:用1个字节的最低位存储,其他7位用0填补。

3、4个字节:在《Java虚拟机规范》一书中的描述:“虽然定义了boolean这种数据类型,但是只对它提供了非常有限的支持。在Java虚拟机中没有任何供boolean值专用的字节码指令,Java语言表达式所操作的boolean值,在编译之后都使用Java虚拟机中的int数据类型来代替,而boolean数组将会被编码成Java虚拟机的byte数组,每个元素boolean元素占8位”。也就是说JVM规范指出boolean当做int处理,也就是4字节,boolean数组当做byte数组处理,这样我们可以得出boolean类型占了单独使用是4个字节,在数组中是确定的1个字节。

综上总结:java规范中,没有明确指出boolean的大小。在《Java虚拟机规范》给出了4个字节,和boolean数组1个字节的定义,具体还要看虚拟机实现是否按照规范来,所以1个字节、4个字节都是有可能的。

浮点的取值范围为何比long还要大

浮点型的空间大小并不比long大但是取值范围却更广,这是因为浮点型的存储遵循 IEEE 754标准

符号位(S):1bit 

指数位(E):8bit 

尾数位(M):23bit

指数位E:8位【0~255】,为了方便比较计算存储的都是正数,实际指数要减掉127;

尾数位M:23位,整数位被舍弃固定1,M取值范围[1.0,2.0);尾数23位取二进制1.11111(23位),约等于2-2^-23≈2

所以float的绝对值最大为:2^127*2=2^128=3.4E+38(科学计数法)

浮点型的有效位数怎么来的

如 float,由其存储结构可看出有23位用于存放尾数, 带有一个固定隐含位… 所以float的有24个二进制有效位位数。2^24=16777216共有8个十进制位. 所以有些编译器 float的有效数字位是 8位 , 有些有效数字位是 7位.(注意不是小数的位数, 是有效数字位)

为什么说浮点型计算往往不准确

 尝试System.out.println( 2.0-1.1 ) 将打印出 0.8999999999999999,而不是人们想象的0.9。原因是浮点型的二进制存储表示方法,而在二进制中无法精确表示小数。

十进制小数到二进制小数一般是整数部分除 2 取余,逆序排列,小数部分使用乘 2 取整数位,顺序排列。二进制小数到十进制小数还是使用按权相加法,实践可知很多十进制无法转成精确的二进制表示(无限循环),连表示都无法准确,计算就无法保证精确了。如果在数值计算中不允许有任何舍入误差,就应该使用 BigDecima类。

引用数据类型

java语言中引用数据类型非常多,比如:类class引用、 接口interface引用、 数组类型、 枚举等等;例如String类就是引用类型;引用类型的赋值传递的是内存的地址。所有引用类型的默认值都是null。

一个引用变量可以引用任何相兼容的类型。

基本数据类型和引用数据类型的区别

1、内存空间指向

基本数据类型指向具体数值,引用数据类型指向该数据存储地址值,赋值和传递同理。

基本数据类型数值存在栈内存;而引用数据类型在堆内存存储数据信息,同时在栈内存中分配空间指向堆中的对象地址。

通过以下代码示意两种存储

    public static void main(String[] args) {
        //基本数据类型
        int age=18;
        int age1=30;
        double price=1.2;
        char code='A';

        //引用数据类型
        String name="lilei";
        String name2="lilei";
        String name3="hanmeimei";
    }

基本数据类型会存在两个相同的值,而引用型类型就不会存在相同数据。

创建声明 String name="lilei";时会在堆内存中查询是否有这个地址,如果堆内存中已经存在则指向这个地址,如果没有就会在堆内存创建并将变量指向地址。

 2、判断数据是否相等

基本数据类型用==和!=判断,引用数据类型:用equals()方法;==和!=是比较数值,而equals()方法是比较内存地址。

3、参数传递方式

基本数据类型调用方法时作为参数是按数值传递的,调用方法时在栈中开辟新内存空间,方法结束时释放,方法内的操作都是操作当前方法执行的栈中的值;

引用数据类型变量调用方法时作为参数传递的是引用的副本(堆内存的地址),调用时为形参(入参变量)在栈中开辟新空间,并指向实参的具体内容(堆内存地址),方法内是直接指向的堆空间中引用类型的值,方法执行完毕后释放栈内存;

据此总结:

  • 参数是基本数据类型,为数值传递,方法内部不会改变外部对象值。
  • 参数为引用数据类型,为地址传递,方法内部会改变外部对象值。
  • 需要特别说明:参数为基本数据类型的包装类型,为引用传递,方法内部改变参数的值,外部变量不会发生变换。

  这是因为包装类型虽然为引用类型传递,但由于自动装箱的机制,在改变包装类对象的值时,是创建一个新的对象,栈中的地址指向了新的对象,不会改变原有的包装类对象。

代码示例:

public static void main(String[] args) {
        //基本数据类型
        int age=18;

        //引用数据类型
        String name="lilei"; //基本包装类
        Person person = new Person("张三",18);

        System.out.println("基础数据类型调用前:"+age);
        System.out.println("引用数据类型调用前(包装类):"+name);
        System.out.println("引用数据类型调用前:"+person.getInfo());
        func(age,name,person);
        System.out.println("基础数据类型调用后:"+age);
        System.out.println("引用数据类型调用后(包装类):"+name);
        System.out.println("引用数据类型调用后:"+person.getInfo());

    }


    public static void func(int age,String name,Person person){
        age=30;
        name="hanmeimei";
        person.setAge(30);
    }

    @Data
    static class Person{
        String name;
        int age;

        public Person(String name,int age){
            this.name = name;
            this.age = age;
        }

        public String getInfo(){
            return "姓名:"+ name + ",年龄:" + age;
        }
    }

类型之间的转换

数据运算处理中会存在类型转换,java中的类型转换分为两类:自动类型转换和强制类型转换。

从小类型到大类型(或者子类到父类)是可以自动转换,在基本数据类型中其顺序如下:

而大类型转小类型(或者父类到子类)则需要强制转换符进行强制转换

需要注意:

  • 布尔类型不能参与类型转换。
  • 引用类型的转换必须要是发生在有继承关系的对象之间

自动类型转换

必须满足转换前的数据类型的范围要低于转换后的数据类型,否则编译报错

        int age=18;
        double age1 =age;
        int age3=age1; // 类型转换异常

上面的代码中,int->doubles 自动转换的,反之不行,编译异常

强制类型转换

        int age=18;
        double age1 =age;
        int age3= (int) age1;

上例double->int 需要加(int)强制转换符号;注意强制转换可能导致精度丢失

可以使用instanceof关键字判断对象是否属于某个数据类型​

 if(引用变量 instanceof 数据类型){

​ 可以转换

​ }else{

​ 不能转换

​ }

基本数据类型及其包装类的转换

基本数据类型对应的包装类也是引用数据类型。他们之间的转换过程存在装拆箱机制。

把基本数据类型转换成包装类的过程就叫装箱,把包装类转换成基本数据类型的过程就是拆箱;在运算和比较操作时会进行自动拆装箱。需要注意:

  • equals()方法不会进行类型转换
  • 如果数字在 -128 至 127 之间时,自动装箱会直接使用缓存中的对象,而不是重新创建一个对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值