Java中的包装类

时间:2024-10-09 19:04:52

一、包装类(wrapper)

所有的包装类都有 final 修饰的。

public final class Paper {
}
  • 1
  • 2

当定义但没有赋值的变量直接打印会报 Variable 'a' might not have been initialized 的错误,是因为未赋值的变量不能直接打印,但其是由默认值的。
在这里插入图片描述

1.不变类

final 修饰的某个类,且该类中的所有实例变量都是不可更改的。

  • 所有变量是 final 修饰的
  • 若类中的变量不是通过 final进行修饰的实例变量,则对其不提供修改的方法,但是这回种方法并 不可靠(所以不提倡)
判断是否为不变类的两个条件:
  1. 被 final 修饰的类(最终变量)
  2. 不可更改的实例变量。
package com.kaifamiao.wrapper;

public final class Paper {

    private final String color;
    private final String size;
    private final int count;

    public Paper(String color, String size, int count) {
        this.color = color;
        this.size = size;
        this.count = count;
    }

    @Override
    public String toString() {
        return "这个纸张是" + color +"的,大小为" + size + ",有" + count + "张。";
    }

    public static void main(String[] args) {

        Paper p = new Paper("白色" , "A4" , 1);
        System.out.println(p);

        Paper a = new Paper("黑色" , "B4" , 3);
        System.out.println(a);

        a =  new Paper("红色" , "A6" , 6);
        System.out.println(a);

    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
不变对象

一经创建再也不能改变其内部的实例变量的值。(变得是 变量的值 ,不变的是 变量本身

在这里插入图片描述

2.包装类的八种基本类型

其中所有基本数据类型所对应的包装类的父类都是 Number。
在这里插入图片描述

基本数据类型(primitive) 包装类(都是 中的)
byte Byte
short Short
int Integer
long Long
float Float
double Double
boolean Boolean
char Character
(忽略)void Void
  1. 使用 valueOf(primitive) 方法将相应的 基本数据类型数值 包装到对象中。
  2. 从 Java 9 开始,已经将8种数值类型对应的包装类中的构造方法 全部废除
  3. 在这里插入图片描述
自动装箱(auto-boxing)

自动 将一个基本数据类型的数据包裹到其相应的包类类型的实例中。(是 JDK 1.5 的老特性)。

    public static void main(String[] args) {
        int i = 100;
        Integer a = Integer.valueOf(i);
        System.out.println(a);

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在这里插入图片描述
(int i)为例:

通过观察 valueOf(int i) 的源代码我们可以发现,其事先为 -128~127 的数据缓冲下来,成为实例,通过表达式:
I n t e g e r C a c h e . c a c h e [ i + ( − I n t e g e r C a c h e . l o w ) ] [i + (-)] IntegerCache.cache[i+(IntegerCache.low)]
在 java 语言规范中:

if the value p being boxed is an integer literal of type int between -128 and 127 inclusive (§3.10.1), or the boolean literal true or false (§3.10.3), or a character literal between '\u0000' and '\u007f' inclusive (§3.10.4), then let a and b be the results of any two boxing conversions of p. It is always the case that a == b.
如果一个变量 p 的值属于:-128至127之间的整数,true 和 false的布尔值,’u0000′ 至 ‘u007f’ 之间的字符中时,将 p 包装成 a 和 b 两个对象时,可以直接使用 a == b 判断 a 和 b 的值是否相等。

A boxing conversion may result in an OutOfMemoryError if a new instance of one of the wrapper classes (Boolean, Byte, Character, Short, Integer, Long, Float, or Double) needs to be allocated and insufficient storage is available.

计算出其数据的下标,从而与缓冲区相对应。这样可以 提高效率 。之后超出的便重新定义对象。都对于 double 和 float 并不是这样的,因为要是做这样的缓冲区了话,只能存放不精确的值。 而对于 char 类型的来说,范围是 0~127 ,因为 char 类型的值都为正数,而 boolean 类型只有两个值,用三元表达式就可以解决。

    @IntrinsicCandidate
    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

(int i)

    @IntrinsicCandidate
    public static Boolean valueOf(boolean b) {
        return (b ? TRUE : FALSE);
    }
  • 1
  • 2
  • 3
  • 4

使用 valueOf(primitive) 方法获取基础数据类型数值对于的包装类型对象可以休闲使用已经 缓存的值

自动拆箱(auto-unboxing)

就是自动将包装类实例中的值取出。

本质上时调用了 primitiveValue() 方法来获取的。(这里的 primitive是指 byte , short , int , long , float , double )都继承了Number类(抽象)。

        boolean b1 = c.booleanValue();
        System.out.println(b1);
  • 1
  • 2

booleanValue() 方法

    @IntrinsicCandidate
    public boolean booleanValue() {
        return value;
    }
  • 1
  • 2
  • 3
  • 4
手动拆箱

通过调用相应的方法来获取得包装类实例中的值。

(3)将字符串转化为基本数据类型的数值(除了character)

primitiveValue() 方法相似。
p a r s e P r i m i t i v e ( P r i m i t i v e ) ; parsePrimitive(Primitive); parsePrimitive(Primitive);
其中的 Primitive 是指出去 char 类型的 7中基本数据类型,float 和 double 类型只有十进制,而 boolean类型 只有输入 “true”时才为 true

2.接口(interface)

某种事物有什么能力(可以完成什么)。

在这里插入图片描述
对于接口只能声明一个接口类型的引用变量,但不能 new 出来实例。
在这里插入图片描述

package com.kaifamiao.wrapper;

public class TestBook {
    public static void main(String[] args) {
        BookMarks f = null;
        f = new Book();
        f.Page();
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

运行结果:
在这里插入图片描述
即为在具体类实现接口中实现的同名方法:

    @Override
    public void Page() {
        System.out.println("这是第7页");
    }
  • 1
  • 2
  • 3
  • 4

并且不仅可以调用原本的方法,也可以调用从父接口继承的方法,以及 Object 类中的方法。
在这里插入图片描述

修饰符 class 类名 implements 接口 {}
  • 1

用具体类实现接口的时候,需要实现接口中所有的方法。

public class Book implements BookMarks{

    @Override
    public void Page() {
        System.out.println("这是第7页");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

并且在接口中所有为实现的方法的修饰符都为 public , abstract。并且所有接口都为抽象的。

3.为什么要有包装类?

因为随着数据的增加,堆中的数据会随之增加,而对于创建的一个新实例来说,要从存储在栈中的地址来引用,从这么多数据中寻找一个很小的变量既费时又费资源,所以索性将这些数据打包装进堆中。