【数据结构】包装类、初识泛型

🎇🎉🎉🎉点进来你就是我的人了
博主主页:🙈🙈🙈戳一戳,欢迎大佬指点!
人生格言: 当你的才华撑不起你的野心的时候,你就应该静下心来学习!
欢迎志同道合的朋友一起加油喔 💪💪💪
目标梦想:进大厂,立志成为一个牛掰的Java程序猿,虽然现在还是一个🐒嘿嘿
谢谢你这么帅气美丽还给我点赞!比个心

目录

  • [1. 包装类(类类型)](#1. 包装类(类类型))
    • [1.1 基本数据类型和对应的包装类](#1.1 基本数据类型和对应的包装类)
    • [1.2 装箱和拆箱](#1.2 装箱和拆箱)
    • [1.3 手动装箱和手动拆箱](#1.3 手动装箱和手动拆箱)
  • [2. 什么是泛型](#2. 什么是泛型)
  • [3. 引出泛型](#3. 引出泛型)
    • [3.1 语法](#3.1 语法)
    • [3.2 <>里面的占位符](#3.2 <>里面的占位符)
  • [4. 泛型类的使用](#4. 泛型类的使用)
    • [4.1 语法](#4.1 语法)
    • [4.2 示例](#4.2 示例)
    • [4.3 类型推导(Type Inference)](#4.3 类型推导(Type Inference))
  • [5 裸类型(Raw Type) (了解)](#5 裸类型(Raw Type) (了解))
  • [6 泛型如何编译的](#6 泛型如何编译的)
    • [6.1 擦除机制](#6.1 擦除机制)
  • [7. 泛型的上界](#7. 泛型的上界)
    • [7.1 语法](#7.1 语法)
    • [7.2 示例](#7.2 示例)
    • [7.3 复杂示例](#7.3 复杂示例)
  • [8. 泛型方法](#8. 泛型方法)
    • [8.1 定义语法](#8.1 定义语法)
    • [8.2 示例](#8.2 示例)

1. 包装类(类类型)

  • 在Java中,由于基本类型不是继承自 Object,为了在泛型代码中可以支持基本类型, Java给每个基本类型都对应了一个包装类型

1.1 基本数据类型和对应的包装类

基本数据类型 包装类
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean

总结:除了 IntegerCharacter , 其余基本类型的包装类都是首字母大写
包装类好处:比如数字转为字符串...

1.2 装箱和拆箱

装箱(也叫做装包):

把一个 基本类型 转变为 包装类型

拆箱(也叫做拆包):

把一个 包装类型 转变为 基本类型

java 复制代码
public static void main(String[] args) {
        int a = 10;
        Integer ii = a;//自动装箱

        Integer ii2 = new Integer(10);
        int b = ii2;

        System.out.println("ii = " + ii);
        System.out.println("b = " + b);

    }

通过反汇编看源码是如何实现的:

1.3 手动装箱和手动拆箱

java 复制代码
public static void main(String[] args) {
        int a = 10;
        Integer ii = Integer.valueOf(a);//手动装箱

        Integer ii2 = new Integer(10);
        int b = ii2.intValue();//手动拆箱
        
        System.out.println("ii = " + ii);
        System.out.println("b = " + b);
    }

【面试题】

下列代码输出什么,为什么?

java 复制代码
//下面就发生了一个装箱过程
public static void main(String[] args) {
        Integer ii = 100;
        Integer ii2 = 100;
        System.out.println(ii == ii2);//true

        Integer a = 200;
        Integer b = 200;
        System.out.println(a == b);//false
    }

2. 什么是泛型

只要会用就行

一般的类和方法,只能使用具体的类型: 要么是基本类型,要么是自定义的类。如果要编写可以应用于多种类型的 代码,这种刻板的限制对代码的束缚就会很大。 ----- 来源《Java编程思想》对泛型的介绍。

泛型是在JDK1.5引入的新的语法,通俗讲,泛型: 就是适用于许多许多类型从代码上讲,就是对类型实现了参数化。

泛型在 c++ 里面是模版

3. 引出泛型

实现一个类,类中包含一个数组成员,使得数组中可以存放任何类型的数据,也可以根据成员方法返回数组中某个下标的值?

java 复制代码
public static void main(String[] args) {
        MyArray myArray = new MyArray();
        myArray.setArray(0,1);
        myArray.setArray(1,19);
        myArray.setArray(2,"mingzhi");
        String str = (String) myArray.getArray(2);
    }

对上述代码进行修改:

这样在实例化对象的时候 < > 里面可以传 类类型参数,达到通用

java 复制代码
public static void main(String[] args) {
        MyArray<String> myArray = new MyArray();
        myArray.setArray(0,"hello");
        myArray.setArray(1,"wold");
        myArray.setArray(2,"mingzhi");
        String str = myArray.getArray(2);
        System.out.println(str);
    }

所以,泛型的主要目的:就是指定当前的容器,要持有什么类型的对象。让编译 器去做检查。 此时,就需要把类型,作为参数传递。需要什么类型,就传入什么类型。

3.1 语法

java 复制代码
class 泛型类名称<类型形参列表> {
// 这里可以使用类型参数
}

class ClassName<T1, T2, ...,Tn>{}

class 泛型类名称<类型形参列表> extends 继承类/* 这里可以使用类型参数 */ { // 这里可以使用类型参数
}

class ClassName<T1, T2, ...,Tn>extends ParentClass <T1> {
// 可以只使用部分类型参数
}

注意:泛型是编译时期的机制,也意味着运行的时候没有泛型的概念-》JVM当中没有泛型的概念

建议写法:

java 复制代码
//<T> 代表当前类 是一个泛型类
class MyArray<T> {
    //类中包含一个数组成员,使得数组中可以存放任何类型的数据
    //呢只有 Object[]
    //语法规定不能实例化一个泛型类型的数组
    public Object[] array = new Object[10];


    //也可以根据成员方法返回数组中某个 下标的值?
    //提供get set 方法
    public T getArray(int pos) {
        return (T) array[pos];
    }

    //首先假设都是正常情况
    //不考虑 极端情况
    public void setArray(int pos, T val) {
        array[pos] = val;
    }
}

3.2 <>里面的占位符

类名后的 < T > 代表占位符,表示当前类是一个泛型类

了解: 【规范】类型形参一般使用一个大写字母表示,常用的名称有:
E 表示 Element
K 表示 Key
V 表示 Value
N 表示 Number
T 表示 Type

S, U, V 等等 - 第二、第三、第四个类型

4. 泛型类的使用

4.1 语法

java 复制代码
泛型类<类型实参> 变量名;  // 定义一个泛型类引用
new 泛型类<类型实参>(构造方法实参);  // 实例化一个泛型类对象

4.2 示例

java 复制代码
MyArray<Integer> list = new MyArray<Integer>();

注意:泛型只能接受类,所有的基本数据类型必须使用包装类!

4.3 类型推导(Type Inference)

当编译器可以根据上下文推导出类型实参时,可以省略类型实参的填写

java 复制代码
MyArray<Integer> list = new MyArray<>(); // 可以推导出实例化需要的类型实参为 Integer

5 裸类型(Raw Type) (了解)

裸类型是一个泛型类但没有带着类型实参,例如 MyArrayList 就是一个裸类型

java 复制代码
MyArray list = new MyArray();

注意: 我们不要自己去使用裸类型,裸类型是为了兼容老版本的 API 保留的机制 下面的类型擦除部分,我们也会讲到编译器是如何使用裸类型的。

小结:

  1. 泛型是将数据类型参数化,进行传递
  2. 使用 表示当前类是一个泛型类。
  3. 泛型目前为止的优点:数据类型参数化,编译时自动进行类型检查和转换

6 泛型如何编译的

6.1 擦除机制

那么,泛型到底是怎么编译的?这个问题,也是曾经的一个面试问题。泛型本质是一个非常难的语法,要理解好他 还是需要一定的时间打磨。

通过命令:javap -c 查看字节码文件,所有的T都是Object。

在编译的过程当中,将所有的T替换为Object这种机制,我们称为: 擦除机制。

Java的泛型机制是在编译级别实现的。编译器生成的字节码在运行期间并不包含泛型的类型信息。

正确的方式: 【了解即可】

java 复制代码
class MyArray<T> {
    public T[] array;

    public MyArray() {
    }

    /**
     * 通过反射创建 ,指定类型的数组
     *
     * @param clazz
     * @param capacity
     */
    public MyArray(Class<T> clazz, int capacity) {
        array = (T[]) Array.newInstance(clazz, capacity);
    }

    public T getPos(int pos) {
        return this.array[pos];
    }

    public void setVal(int pos, T val) {
        this.array[pos] = val;
    }

    public T[] getArray() {
        return array;
    }
}

7. 泛型的上界

在定义泛型类时,有时需要对传入的类型变量做一定的约束,可以通过类型边界来约束。

7.1 语法

java 复制代码
class 泛型类名称<类型形参 extends 类型边界> {
...
}

7.2 示例

java 复制代码
public class MyArray<E extends Number> {
...
}

只接受 Number 的子类型作为 E 的类型实参

java 复制代码
MyArray<Integer> l1;        // 正常 ,因为 Integer 是 Number 的子类型    
MyArray<String> l2;     // 编译错误 ,因为 String 不是 Number 的子类型

了解: 没有指定类型边界 E,可以视为 E extends Object

7.3 复杂示例

java 复制代码
public class MyArray<E extends Comparable<E>> {
...
}

E必须是实现了Comparable接口的

擦除机制,当擦除为 Object 时,引用数据类型不能,直接通过大于等于号进行比较

java 复制代码
//写一个泛型类,求数组当中的最大值
class Alg<T extends Comparable<T>>{
    public T findMaxVal(T[] array){
        T max = array[0];
        for (int i = 1; i < array.length; i++) {
            if (array[i].compareTo(max) > 0){
                max = array[i];
            }
        }
        return max;
    }
}

传入的T一定实现 Comparable 接口,所以就能使用compareTo 方法

8. 泛型方法

8.1 定义语法

java 复制代码
方法限定符 <类型形参列表> 返回值类型 方法名称(形参列表) { ... }

8.2 示例

java 复制代码
public class Util {
    //静态的泛型方法 需要在static后用<>声明泛型类型参数
    public static <E> void swap(E[] array, int i, intj) {
        E t = array[i];
        array[i] = array[j];
        array[j] = t;
    }
}
java 复制代码
//泛型方法
class Alg2{
    public<T extends Comparable<T>> T findMaxVal(T[] array){
        T max = array[0];
        for (int i = 1; i < array.length; i++) {
            if (array[i].compareTo(max) > 0){
                max = array[i];
            }
        }
        return max;
    }
}

也可以不实例化,把泛型方法设置为静态的泛型方法

java 复制代码
class Alg3{
    public static <T extends Comparable<T>> T findMaxVal(T[] array){
        T max = array[0];
        for (int i = 1; i < array.length; i++) {
            if (array[i].compareTo(max) > 0){
                max = array[i];
            }
        }
        return max;
    }
}
相关推荐
Dfreedom.4 分钟前
一文掌握Python四大核心数据结构:变量、结构体、类与枚举
开发语言·数据结构·python·变量·数据类型
pengzhuofan44 分钟前
第10章 Maven
java·maven
百锦再1 小时前
Vue Scoped样式混淆问题详解与解决方案
java·前端·javascript·数据库·vue.js·学习·.net
刘一说1 小时前
Spring Boot 启动慢?启动过程深度解析与优化策略
java·spring boot·后端
壹佰大多1 小时前
【spring如何扫描一个路径下被注解修饰的类】
java·后端·spring
百锦再2 小时前
对前后端分离与前后端不分离(通常指服务端渲染)的架构进行全方位的对比分析
java·开发语言·python·架构·eclipse·php·maven
DokiDoki之父2 小时前
Spring—注解开发
java·后端·spring
知花实央l2 小时前
【算法与数据结构】拓扑排序实战(栈+邻接表+环判断,附可运行代码)
数据结构·算法
吃着火锅x唱着歌2 小时前
LeetCode 410.分割数组的最大值
数据结构·算法·leetcode
CodeCraft Studio2 小时前
【能源与流程工业案例】KBC借助TeeChart 打造工业级数据可视化平台
java·信息可视化·.net·能源·teechart·工业可视化·工业图表