ZB-007-java数据类型

数据类型

  • int 4字节 (4bytes 32bit)

    1
    2
    3
    int a = 10;
    int b = 011; //8进制
    int c = 0x11; // 16进制
  • char 2字节

  • short 2字节

原生数据类型和引用数据类型

原生 引用
int a= 1 String s = “a”
4字节存放 1这个值 假设 地址值:1234 存放 字符串”a”
  • 只要能找到对应的类,就是引用数据类型
  • 否则是原生数据类型

基本数据类型

  • byte 1字节
  • short 2字节
  • int 4字节(最大21亿)
    针对淘宝这种亿级用户最好不要用int使用 long
  • long 8字节
  • float 4字节
  • double 8字节
  • char 2字节
  • boolean true/false
  • void? 不返回任何类型
1
2
3
4
5
6
7
8
9
10
int a = 1;
byte b = (byte)128; // 会丢失精度
long c = 22_0000_0000L; // 不推荐用 "l" 与 “1” 容易歧义
float d = 0.1f;
double e = 2e-3; //科学计数法


//
int f = 0x123; // 十六进制
int g = 0b1010101; // 二进制, java7之后出现的

如果你想知道原生数据类型的最大最小值是什么?

  • 每一个原生数据类型对应一个装箱数据类型
  • 对应的装箱数据类型里有两个常量 MIN_VALUE/MAX_VALUE

问题来了?如果强行存储超过范围的值会怎么样?

  • 会溢出

浮点数是小数,在计算机中是近似表示

  • 浮点数只能比较大小,不要比较“相等
1
2
3
4
5
6
7
8
9
10
// 
float i = 0.1f;
if(i==0.1f){

}

double d = 0.2;
if(Math.abs(d - 0.2) < 0.000001){

}

类型转换

  1. 整数除法是地板除
  2. 将所有类型提升到最⾼精度进⾏计算

    1
    2
    3
    int i = 1 + 1; // ok
    int b = 1 + 1.0;// not ,因为 1.0是双精度所以 类型都被提升了, 所以 结果是 double 值 需要强制类型转化
    int c = (int)(1 + 1.0); // ok
  3. 丢失精度时需要进⾏强制转换

  4. char参与计算时使⽤ASCII码(Unicode码)
    1
    2
    3
    4
    5
    6
    7
    8
    char c1 = 'a';
    char c2 = 'A';
    char c3 = '你';

    char c4 = '1'; // 对应ASC码 为 49
    // c4 = c4 + 1; // 报错因为 + 1 是和 int值进行计
    算 必须进行强制转换
    c4 = (char)(c4 + 1); // c4的值是49 ,49+1 =50 ,50对应的字符是 '2'
  • 自动转换

    1
    2
    byte b = 100;
    int i = b; // 可以直接转换
  • 强制转换

    1
    2
    int i = 200;
    byte b = (byte) i; // 因为已经溢出了,所以要强制转换

整数除法计算是 地板除(向下取整)

1
2
3
4
5
6
7
8
9
10
11
12
13
int a = 3;
int b = 2;
int c = a / b; // 1


// 因为设置了返回值是 double 所以 result 会自动提升为 double
public static double divide(int a ,int b){
int result = a / b;
return result;
}


divide(3,2) // 1.0

精度问题,所有表达式中,参与计算的表达式都会提升到最高的精度进行计算,最后的结果也是最高精度

1
2
3
4
5
int i = 1 + 1; // 没问题

// int i2 = 1 + 1.0; // 有问题 与浮点数计算会变成double
// 只能这样 强制转换
int i2 = (int)(1 + 1.0);

解决整型地板除损失精度问题

1
2
3
4
5
6
7
8
9
10
11
public static double divide(int a ,int b){
double result = 1.0 * a / b;
return result;
}

// 或者

public static double divide(int a ,int b){
double result = (double)a / b;
return result;
}

void 类型

  • 所有的类型可以 类型.class 得到它的 class值
1
2
3
Class c = String.class;
Class intCLass = int.class;
Class voidCLass = void.class;

装箱类型(引用类型)

  • Byte(byte)
  • Short(short)
  • Integer(int)
  • Long(long)
  • Float(float)
  • Double(double)
  • Character(char)
  • Boolean(boolean)
  • Void?(void)

任何原生数据类型都有对应的装箱类型

自动装箱/自动拆箱

1
2
3
4
5
public static int add(int i){ return new Integer(i);}

int i = 100;
Integer integer = i; // 自动装箱
add(integer); // 自动拆箱

为什么要有引用类型

  • 容器类不接受原⽣数据类型
    1
    2
    3
    // List里只接受引用类型,不接受原生类型
    List<Integer> a = new ArrayList<>();
    a.add(1); // 丢进去的是 int 自动装箱 为 Integer
  • 可以赋值为null

    1
    2
    3
    4
    // boolean 只能有两种状态 true/false

    // 而装箱类型还有第三种状态 true/false/null
    Boolean state = null;
  • 提供额外的⽅法

    1
    2
    3
    4
    5
    String s = "123";
    // 内存中对应 是一个 char[] 数组

    // 而数字 内存中 4字节 01组成的序列
    int i = 123;
  • ⾃动装箱与拆箱

原⽣类型与引⽤类型带来的坑

  • 对null拆箱将引发空指针异常

    1
    2
    Integer a = null;
    int i = a;// 空指针异常
  • ==与equals约定

    1
    2
    3
    4
    5
    6
    7
    8
    9
    int a = 5;
    int b = 5;
    a == b // true

    Integer c = 1000; // 假设内存地址 512
    Integer d = 1000; // 假设内存地址 600
    c == d // false 因为 “==“ 比较的是值,而引用类型的值是 ”地址“ 512 != 600

    c.equals(d) // true

“==”

比较二者是否相同

“equals()”

比较二者是否是不是相等

  • 让你惊讶的地方!!!

  • 让你惊讶的地方!!!

  • 让你惊讶的地方!!!

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    Integer e = 1;
    Integer f = 1;

    e == f // true 竟然相等了?
    e.equals(f) // true


    int类型是占据 4字节的空间,
    而 Object / Integer 这类引用数据类型 远比int占据的空间要多

    如果你频繁
    Ingeter i = 1; // 占据空间远远大于4字节
    Ingeter b = 2; // 占据空间远远大于4字节

    所以java偷偷做了一件事
    对于非常小的数字则认为是常用的数字。
    则对其进行缓存 具体参考 IntegerCache的文档
    会对 -128~+127的 数字进行缓存,而不是重新创建对象

顺便提一句:Integer对象是不可变的

1
2
3
Integer c = 1; // 内存地址 509
c = c + 1; // +1 操作 此时 c的地址变成了 512
// Integer 本身是不可变的

数组类型

面试题:请你给我解释一下数组是什么,为啥我没看见过数组类型的声明,却可以直接用呢?

  • 数组类型是一种特殊的类型,JDK负责创建它

由JDK负责创建的特殊类型

  • X[] x = new X[10] 长度为10的数组
  • X[] x = new X[]{5,4,3,2,1} 长度为5的数组
  • X[] x = {5,4,3,2,1}
  • 其中 X 也可以是数组类型
    1
    int[][] c = new int[][]{{1,2,3},{4,5,6}}

数组的主要特性

  • 长度不可变
  • 类型安全 String[] c = {"a","b"}; // 声明了是 String 就不能丢其他类型的东西
  • 只有一个 length 属性
  • 可以用下标去取对应元素 a[1]
  • 可以使用 for 循环