数据类型

Java中的数据类型:
Java数据类型 - 图1

基本数据类型

1. 整数类型

数据类型 存储空间 封装类 默认值 取值范围
byte 1字节(8位) Byte 0 -128~127
short 2字节(16位) Short 0 -32768~32767
int 4字节(32位) Integer 0 -2147483648~2147483647
long 8字节(64位) Long 0

注意:为long型变量赋值,如果值的大小没有超过int的范围,那么可以省略L(隐式类型转换),否则必须加上L,不然会报错。 这是因为在Java中为基本数据类型赋值不能超过其取值范围,一旦超过就会报错。在为long类型变量赋值时不加L,默认认为是int类型,所以值超过int类型会报错。

Java数据类型 - 图2
  整数类型在Java中有表示类型:十进制、八进制、十六进制、二进制。

   十进制:直接赋值
   八进制:在值前面加数字”0“
   十六进制:在值前面加数字和字母”0x“
   二进制:在值前面加0b

  1. package test;
  2. public class text{
  3. public static void main(String[] args) {
  4. int decimal = 12;//十进制赋值
  5. int octal = 012;//八进制赋值
  6. int hexadecimal = 0x12;//十六进制赋值
  7. System.out.println(decimal);
  8. System.out.println(octal);
  9. System.out.println(hexadecimal);
  10. }
  11. }

  上面代码给decimal赋十进制的12,给octal赋八进制的12,给hexadecimal赋十六进制的12,输出结果:

decimal的值:12
octal的值:10
hexadecimal的值:18

   另外可以为数字字面量使用下划线_,这些下划线只是为了让人容易阅读使用(例如100_000表示10万),Java编译器会去除这些下划线。
注意:

  1. 除了数字0,其他任何十进制数不能以0开头。
  2. 八进制数必须以0开头。(这也是十进制不能以0开头的原因,如果十进制可以以0开头的话,012到底是十进制还是八进制就分不清了)
  3. 十六进制必须以0x开头。

2. 浮点型

数据类型 存储空间 封装类 默认值 取值范围
float 4字节(32位) Float 0.0F 1.4E-45~3.4028235E38
double 8字节(64位) Double 0.0 4.9E-324~1.7976931348623157E308

  1. 在默认情况下,小数被认为是double类型。所以在给float型数据赋值的时候必须要在值的后面加F或者f,标明这是个float数据,如果不加f或者F会报错。(因为double型数据空间比float空间大,而小数默认是double类型,double类型不能直接赋值给float型数据),而double型数据在值的后面加不加d或者D都可以。
  2. 注意到float存储空间和int一致,但是float表示的值范围远大于int,按理来说,float和int存储空间一致,那么他们表示的数据的个数应该是一样的(都是2个数据),为什么float比int范围大那么多?
这是因为float是科学计数法的存储表示,在这32位存储空间中,一部分存储数值(23bit),一部分存储指数(8bit),还有1bit是符号位。
能够看出来float在靠近零的区域相邻两个数值间隔小,在远离零的区域间隔大。(这是由于指数的原因,数值每变化1,整体数值变化2。在靠近零的范围内,指数是负值,数值每变化1,整体数值变化就小;在远离零的地方,指数是正值)
现在再来看int和float的区别,int的32位存储的2个数据的相邻数据间隔是1。所以float存储的数值个数和int确实是一样的,只是float将相邻数值的间隔改变了。
  3. 使用浮点型数据进行的操作基本是比较大小,==都不会用到,因为浮点型数据是近似值不是准确值。

  现在考虑一个问题,下面代码输出是true还是false?

public class text {
    public static void main(String[] args) {
        float f1 = 4294967244f;
        float f2 = 4294967243f;
        float f3 = 1832414f;
        System.out.println(f1 == f2);
        //System.out.println(f1);
    }
}

  看上去,这两个变量不相等,应该输出false,但是事实上输出结果是true,这是为什么呢?我们尝试输出下f1和f2,发现输出的值都是4.2949673E9,这表示f1和f2在计算机中存储的值都是4294967300,这其实是4294967244超过了float存储数值部分的上限,因此只存储了高位部分。float存储数值的有效位数(准确位数)是7位,double的有效位数是16位。在判断大小的时候,不能直接像int那样比较。
  在来看一段代码:

double a = 2.0;
double b = 1.1;
System.out.println(a-b);

输出:

0.8999999999999999

  精准运算中不能使用浮点型计算。事实上造成上面结果的原因是二进制无法精确表示1/10,就如同十进制中无法精确表示1/3。如果需要精确计算的话,可以使用BigDecimal这个类。

3. 字符型

数据类型 存储空间 封装类 默认值 取值范围
char 2字节(16位) Character \u0000(空格) \u0000~\uffff

  定义字符型变量需要用单引号括起来(双引号括起来的是字串),并且单引号之间必须是一个字符(转义字符除外)。没有字符和两个以上字符都不行。
需要记住一些转义字符:

转义字符 含义
\n 换行符
\t 制表符,类似tab键
\\ \
\‘

  注:

char c = 61;

  这种写法成立,但是c存储的并不是61这个整数,而是61对应的编码表上的字符。

4. 布尔型

  1字节。默认值:false
  只有true和false两个值,Java中布尔型不能和整数0,1相互转化。

引用数据类型

  Java中有五类引用数据类型:类、接口、数组、枚举、标注
  引用数据类型的默认值是:null
  基本数据类型:保存在栈内存中的简单数据
  引用数据类型:保存在栈内存中的引用名指向保存在堆内存中的对象,类似指针/地址。如:String s = new String(“abc”);(=左边保存在栈内存,=右边是堆内存中)