数据类型

  • 分为基本数据类型和非基本数据类型(复合数据类型)(又名引用数据类型)

    • 基本数据类型:整型,字符型…
    • 复合数据类型:数组 类 字符串 接口…

      基本类型

  • java基本类型因为是使用频率很高的,而new创建的对象都是保存在堆内存中的,读取速度较慢。而且先获取对象再获取对象值也不如直接获取值方便,所以有了基本类型

  • java明确了每种基本类型的内存占用大小,不随着平台而改变 | 基本类型 | 大小 | 最小值 | 最大值 | | —- | —- | —- | —- | | boolean | — | — | — | | char | 16 bits | Unicode 0 | Unicode 216 -1 | | byte | 8 bits | -128 | +127 | | short | 16 bits | - 215 | + 215 -1 | | int | 32 bits | - 231 | + 231 -1 | | long | 64 bits | - 263 | + 263 -1 | | float | 32 bits | IEEE754 | IEEE754 | | double | 64 bits | IEEE754 | IEEE754 | | void | — | — | — |

字符类型

  • 字符常量有两种字符类型普通字符转义字符
  • 转义字符可以用在单/双引号
  • 占用2个字节(一个字节为8位)

    整型

    数据类型 - 图1
    整型常量有十进制、八进制和十六进制三种表示方法

  • 1234(十进制,无变化)

  • 0777(八进制,以数字 0 开头) 0具有迷惑性,所以少使用8进制
  • 0x3ABC(十六进制,以 0x/0X开头)
  • 长整型以L/l后缀表示
  • java7之后可以加上前缀 0b 或 0B 就可以表示二进制

    浮点型

    数据类型 - 图2

  • float用F/f 无F/f的默认为double,double还可以D/d表示

  • double叫做双精度浮点型,因为它精度是float精度的2倍。
  • 绝大部分应用程序都采用 double 类型。在很多情况下,float 类型的精度很难满足需求。实际上,只有很少的情况适合使用 float 类型,例如,需要单精度数据的库, 或者需要存储大量数据。

除了小数形式,还有科学计数法(用e/E表示10的幂次方)
如123.24e40表示123.24乘以10的40次方

浮点型运算

  • 浮点数类型与整数不同,当执行运算时如果出现某种不正常的状态,浮点数类型不会抛出异常。例如,如果用 0 除浮点数类型的变量,则计算结果是一个特别的无限值、
  • 浮点数值不适用于无法接受舍入误差的金融计算中。 例如,命令 System.out.println ( 2.0-1.1 ) 将打印出 0.8999999999999999, 而不是人们想象的 0.9。**这种舍入误差的主要原因是浮点数值采用二进制系统表示, 而在二进制系统中无法精确地表示分数 1/10**。这 就好像十进制无法精确地表示分数 1/3 —样。如果在数值计算中不允许有任何舍入误差, 就应该使用 BigDecimal 类
  • 整数除以 0 除将会产生一个异常如11/0, 而浮点数除以0 会得到无穷大或 NaN 结果sout(11.0/0)->Infinity(即∞)
  • 当参与 / 运算的两个操作数都是整数时, 得到的是整数结果(去尾) 如11/2=5
  • 布尔型

1个字节

BigInteger和BigDecimal

  • 如果基本的整数和浮点数精度不能够满足需求, 那么可以使用 java.math 包中的两个很有用的类:Biglnteger 和 BigDecimal 这两个类可以处理包含任意长度数字序列的数值
    • Biglnteger 类实现了任意精度的整数运算,即大数。
      • 大数不能使用+和*运算符,而是使用add 和 multiply 方法。
    • BigDecimal 实现了任意精度的浮点数运算。
  • 静态方法BigInteger.valueOf()可以将普通整型转为大数

    1. BigInteger a = BigInteger.valueOf(100);
    2. Biglnteger c = a.add(b); // c = a + b
    3. Biglnteger d = c.multiply(b.add(Biglnteger.valueOf(2))); // d = c * (b + 2)

    基本类(包装类)

  • 除了char和int外,其他都是首字母大写得到基本类

    • 前 6 个类派生于公共的超类 Number,而 Character 和 Boolean 是 Object 的直接子类。
    • 包装类都是final类型的,无法被继承 | 基本类型 | 对应的包装类(位于 java.lang 包中) | | —- | —- | | byte | Byte | | short | Short | | int | Integer | | long | Long | | float | Float | | double | Double | | char | Character | | boolean | Boolean |
  • 基本类与对于基本类型可以互相转化。这种转化叫做装箱/拆箱

  • 在java中万物皆对象,而基本类型非常常用,所以有了基本类型,同时又有了包装类。以下即包装类的简陋原型
public class MyInt {
    private int number; // 基本数据类型

    public Int (int number){ // 构造函数,传入基本数据类型
        this.number = number;
    }
    public int intValue(){ // 取得包装类中的数据
        return this.number;
    }
    public static void main(String[] args) {
    MyInt temp = new Int(100); // 100 是基本数据类型, 将基本数据类型包装后成为对象
    int result = temp.intValue(); // 从对象中取得基本数据类型
    System.out.println(result);
}

}
  • 自动装箱的底层原理是调用了包装类的 valueOf 方法,而自动拆箱的底层调用了包装类的 intValue() 方法。

    装箱

  • 创建一个基本类型变量,编译器会自动装箱

Integer n = new Integer(123); 装箱,可以缩写为Integer n=123;
n=n+1; 自动拆箱 基本类运算时会给自动转换为基本类型

  • 如果频繁拆装箱的话,也会严重影响系统的性能。我们应该尽量避免不必要的拆装箱操作。

    拆箱

  • 由基本类对象得到基本类型值

设有 Double 类对象 dObj
double d = dObj.doubleValue();//自动拆
或者double d=dObj; //这是自动拆箱
装箱即基本类型转为基本类,拆箱即基本类转为基本类型

Object类与基本类联系

  • Object是所有类的超类,所以自然能接收基本类类型。Object obj = 10; int temp = (Integer) obj;期间自动实现了装拆箱与上下转型

image.png

IntegerCache缓存

public static void main(String[] args) {
    Integer n1 = 47;
    Integer n2 = 47;
    System.out.println(n1 == n2);   //TRUE
    Integer n3 =128 ;
    Integer n4 = 128;
    System.out.println(n3 == n4);   //false
}
  • Integer 内部维护着一个 IntegerCache 的缓存(一个Integer对象数组),默认缓存范围是 [-128, 127],创建Integer对象时,如果值在这个范围内,就会直接复用缓存数组里的对象
    • 所以 [-128, 127] 之间的2个同值的Integer对象用==会得到true,因为他们是一个对象的两个引用,只是创建了一个新的引用。而对于范围外的值的Integer对象,就是创建了新的对象和引用。
  • 如果是一个类的对象持有Integer字段,那不存在==这个问题(比较一个对象的Integer字段时只需把他看成是基本类型即可,即只是值传递而非引用传递)

class A{Integer aa;
main(){A v1 = new A(),v2 = new A();
v1.i=v2.i = 128;
sout(v1.i==v2.i)} ->true
}
image.png

基本类的缓存

  • Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,Character 创建了数值在 [0,127] 范围的缓存数据,Boolean 直接返回 True or False。

    三种创建Integer对象的方式

  • 第一种自动装箱,本质上就是调用了valueOf()方法。所以第一种和第三种如果是在缓存池中的数值,那返回的只是一个对象复用。超出缓存池,返回的是新对象。而第二种无论是否在缓存池中都返回新的对象 ```java

1.Integer num= 130;

2.Integer num = new Integer(12);

3.Integer num = Integer.valueOf(12);

<a name="vJyG3"></a>
# 类型转换
<a name="AZeXk"></a>
## 自动转换

- 只要是涉及赋值与比较的地方都会发生自动转换

![](https://cdn.nlark.com/yuque/0/2021/png/2319994/1625161457057-f89f8e1e-1beb-4a32-9467-dccf82303fbe.png#clientId=u204dcd64-223c-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=uef957f79&margin=%5Bobject%20Object%5D&originHeight=329&originWidth=503&originalType=url&ratio=2&rotation=0&showTitle=false&status=done&style=none&taskId=ua1b56303-7efc-45c1-bd82-e71299a6dbc&title=)<br />**6 个实心箭头,表示无信息丢失的转换;有 3 个虚箭头, 表示可能有精度损失的转换**。
```java
sout(97=='a')   //true
9.0==9   //true

强制转换

  • 强制类型转换(cast ) 同样有可能会丢失一些信息

double x = 9.997; int nx = (int) x;

  • 如果运算结果溢出了,将溢出的结果转为更大的类型还是错的

    • int a=b=100000;long c=a*b;sout(c) 的结果还是错的。因为a*c运算后才会转换为long。应该这样写:long c=(long)a*b;

      字符串转基本类型

  • 基本类.parse基本类() parse...()都是静态方法,所以使用类名调用

    • 字符型没有**parse...()**方法。取而代之的是一个charAt()方法,该方法属于String方法,可以根据索引提取字符
  • 还可以使用基本类.valueOf()

    String str = "10";
    int temp = Integer.parseInt(str);// String->Integer->int
    System.out.println(temp * 2); // 20
    

    基本类型/字符串转基本类

  • 方法1:通过基本类的构造方法转

  • 方法2:通过基本类.valueOf(基本类型/字符串)转,这种除了Integer外,其他跟方法1一样,但是转Integer时除了返回一个new的对象,还可能返回一个缓冲池中对象的引用
    • 这种方法不能用于字符型

image.png

默认浮点

  • 注意小数默认为double,所以
    • float a=9.0是错误的 因为不能自动将double型转为float
    • 所以需要float a=9.0f/F 或者float a=(float)9.0

      保留小数

      ```java //方法1: float num1 = 3.1415926f; BigDecimal bd = new BigDecimal(num1); float num2 =bd.setScale(2,BigDecimal.ROUND_HALF_UP).floatValue(); //ROUND_HALF_UP表示向上取整,即四舍五入,down则去尾

//如果仅仅是为了输出,加可以通过以下方法转为保留小数的String类型 float num = 3.1415926f; String num1 = String.format(“%.2f”,num); System.out.println(num1); ```