Java基础知识之数据类型

数据类型

  1. java语言是一种强类型语言
  2. 变量或常量必须有类型:声明变量或常量必须声明类型。
  3. 赋值时类型必须一致:值的类型必须和变量或常量的类型完全一致。
  4. 运算时类型必须一致:参与运算的数据类型必须一致才能运算。

java中的数据类型分为基本数据类型引用数据类型

  • 基本数据类型:基本数据类型共有8种,分别是:布尔型boolean, 字符型char和数值型byte/short/int/long/float/double。由于字符型char所表示的单个字符与Ascii码中相应整形对应,因此,有时也将其划分到数值型中
  • 引用数据类型:引用类型具体可分为:数组、类和接口。

    基本数据类型:
    数值类型在内存中直接存储其本身的值,对于不同的数值类型,内存中会分配相应的大小去存储。如:byte类型的变量占用8位,int类型变量占用32位等。相应的,不同的数值类型会有与其存储空间相匹配的取值范围
    这里写图片描述

    在java中整数的默认数据类型是int, 例如数字4, 小数的默认数字类型是double, 例如3.12. 当float a = 3.12时会报错, 因为3.12的默认数据类型是double

看下面例子

public class Test {
    public static void main(String[] args) {
        byte a = 128;   //编译出错
        byte b = 127;   //编译正确

        float c = 3.12; //编译出错
        float d = (float) 3.12; //编译正确
    }
}

将一个int型的128赋值给byte a编译出错,将127赋值给byte b编译正确,为什么呢?
原因在于:jvm在编译过程中,对于默认为int类型的数值时,当赋给一个比int型数值范围小的数值类型变量(在此统一称为数值类型k,k可以是byte/char/short类型),会进行判断,如果此int型数值超过数值类型k,那么会直接编译出错。因为你将一个超过了范围的数值赋给类型为k的变量,k装不下嘛,你有没有进行强制类型转换,当然报错了。但是如果此int型数值尚在数值类型k范围内,jvm会自定进行一次隐式类型转换,将此int型数值转换成类型k。这一点有点特别,需要稍微注意下。

在其他情况下,当将一个数值范围小的类型赋给一个数值范围大的数值型变量,jvm在编译过程中俊将此数值的类型进行了自动提升。在数值类型的自动类型提升过程中,数值精度至少不应该降低(整型保持不变,float->double精度将变高)。

public class Test {
    public static void main(String[] args) {
        long a = 11111111111;   //编译出错
        long b = 11111111111L;   //编译正确

        int z = 10; //编译正确
        long q = z; //编译正确
    }
}

如上:定义long类型的a变量时,将编译出错,原因在于11111111111默认是int类型,同时int类型的数值范围是-2^31 ~ 2^31-1,因此,11111111111已经超过此范围内的最大值,故而其自身已经编译出错,更谈不上赋值给long型变量a了。

此时,若想正确赋值,改变11111111111自身默认的类型即可,直接改成11111111111L即可将其自身类型定义为long型。此时再赋值编译正确。

将值为10的int型变量 z 赋值给long型变量q,按照上文所述,此时直接发生了自动类型提升, 编译正确。

接下来,还有一个地方需要注意的是:char型其本身是unsigned型,同时具有两个字节,其数值范围是0 ~ 2^16-1,因为,这直接导致byte型不能自动类型提升到char,char和short直接也不会发生自动类型提升(因为负数的问题),同时,byte当然可以直接提升到short型。

隐式类型转换
隐式转换也叫作自动类型转换, 由系统自动完成.
从存储范围小的类型到存储范围大的类型.
byte ->short(char)->int->long->float->double

显示类型转换

显示类型转换也叫作强制类型转换, 是从存储范围大的类型到存储范围小的类型.
当我们需要将数值范围较大的数值类型赋给数值范围较小的数值类型变量时,由于此时可能会丢失精度(1讲到的从int到k型的隐式转换除外),因此,需要人为进行转换。我们称之为强制类型转换。

public class Test {
    public static void main(String[] args) {
        byte a = 3;   //编译正确
        int b = 4;   //编译正确
        byte c = a;  //编译错误
    }
}

byte a =3;编译正确在1中已经进行了解释。接下来将一个值为3的int型变量b赋值给byte型变量c,发生编译错误。这两种写法之间有什么区别呢?

区别在于前者3是直接量,编译期间可以直接进行判定,后者b为一变量,需要到运行期间才能确定,也就是说,编译期间为以防万一,当然不可能编译通过了。此时,需要进行强制类型转换。

强制类型转换所带来的结果是可能会丢失精度,如果此数值尚在范围较小的类型数值范围内,对于整型变量精度不变,但如果超出范围较小的类型数值范围内,很可能出现一些意外情况。

public class Test {
    public static void main(String[] args) {
        int a = 233;
        byte b = (byte) a;
        System.out.print(b);
    }
}

上面的例子中输出值是 -23.
为什么结果是-23?需要从最根本的二进制存储考虑。
233的二进制表示为:24位0 + 11101001,byte型只有8位,于是从高位开始舍弃,截断后剩下:11101001,由于二进制最高位1表示负数,0表示正数,其相应的负数为-23。

进行数学运算时的数据类型自动提升与可能需要的强制类型转换

当进行数学运算时,数据类型会自动发生提升到运算符左右之较大者,以此类推。当将最后的运算结果赋值给指定的数值类型时,可能需要进行强制类型转换。例如:

public class Test {
    public static void main(String[] args) {
        int a = 9;
        byte b = 1;
        byte c = (byte) (a + b);
    }
}

a+b会自动提升为int, 因此在给c赋值的时候要强制转换成byte.

猜你喜欢

转载自blog.csdn.net/u013277209/article/details/78830290