专治Java底子差,不要再认为泛型就是一对尖括号了

news2024/11/26 18:30:07

文章目录

  • 一、泛型
    • 1.1 泛型概述
    • 1.2 集合泛型的使用
      • 1.2.1 未使用泛型
      • 1.2.2 使用泛型
    • 1.3 泛型类
      • 1.3.1 泛型类的使用
      • 1.2.2 泛型类的继承
    • 1.4 泛型方法
    • 1.5 泛型通配符
      • 1.5.1 通配符的使用
        • 1)参数列表带有泛型
        • 2)泛型通配符
      • 1.5.2 泛型上下边界
    • 1.6 泛型的擦除
      • 1.6.1 限制擦除
      • 1.6.2 泛型的桥接方法

一、泛型

1.1 泛型概述

泛型定义:把类型明确的工作延迟到创建对象或调用方法的时候才去明确的特殊的类型;

例如,我们知道集合是可以存储任意元素的,那么这样一想,add方法上的参数应该是Object(所有类的父类),但是这样会引入一个新的问题,我们知道,子类都是比父类强大的,我们在使用的时候肯定是希望获取的是当初存进去的具体子类对象;因此我们每次都需要进行强制转换;

但add方法真的是Object吗?

查看ArrayList的add方法:

class ArrayList<E>{ 
    public boolean add(E e){ }

    public E get(int index){ }
   	....
}

Collection类:

public interface Collection<E> extends Iterable<E> {
}

上面的E就是泛型,集合的定义者也不知道我们需要存储什么元素到集合中,具体的类型只能延迟到创建对象时来决定了

1.2 集合泛型的使用

1.2.1 未使用泛型

定义一个Province对象:

package com.dfbz.demo01;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Province {

    private String name;                        // 名称
    private String shortName;                    // 简称
    private String location;                    // 所属区域

    public void intro() {
        System.out.println("名称: " + name + ",简称: " + shortName + ",所属地区: " + location);
    }

    @Override
    public String toString() {
        return "Province{" +
                "name='" + name + '\'' +
                ", shortName='" + shortName + '\'' +
                ", location='" + location + '\'' +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getShortName() {
        return shortName;
    }

    public void setShortName(String shortName) {
        this.shortName = shortName;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public Province() {
    }

    public Province(String name, String shortName, String location) {
        this.name = name;
        this.shortName = shortName;
        this.location = location;
    }
}

测试类:

package com.dfbz.demo01;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo01_泛型问题引出 {
    public static void main(String[] args) {

        Collection list = new ArrayList();

        // 往集合存储对象
        list.add(new Province("台湾", "台","华东"));
        list.add(new Province("澳门", "澳","华南"));
        list.add(new Province("香港", "港","华南"));
        list.add(new Province("河北", "冀","华北"));

        // 获取迭代器
        Iterator iterator = list.iterator();

        while (iterator.hasNext()) {

            // 集合中的元素都被提升为Object对象了
            Object obj = iterator.next();

            // 强制转换为子类
            Province province = (Province) obj;

            // 调用子类特有的功能
            province.intro();
        }
    }
}

我们没有给泛型进行明确的定义,对象存储到集合中都被提升为Object类型了,取出来时需要强制转换为具体子类,非常麻烦;

不仅如此,这样的代码还存在这隐藏的风险,集合中可以存储任意的对象,如果往集合中存储其他对象呢?

定义个Book对象:

package com.dfbz.demo01;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Book {
    private String name;
    private String author;

    public void detail() {
        System.out.println("书名: " + name + ",作者: " + author);
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", author='" + author + '\'' +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public Book() {
    }

    public Book(String name, String author) {
        this.name = name;
        this.author = author;
    }
}

测试类:

package com.dfbz.demo01;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo02_泛型出现的问题 {
    public static void main(String[] args) {
        Collection list = new ArrayList();

        // 添加几个省份
        list.add(new Province("山西", "晋","华北"));
        list.add(new Province("河南", "豫","华中"));
        list.add(new Province("江西", "赣","华东"));

        // 添加几本书
        list.add(new Book("《史记》","司马迁"));
        list.add(new Book("《三国志》","陈寿"));

        // 获取迭代器
        Iterator iterator = list.iterator();

        while (iterator.hasNext()) {

            // 集合中的元素都被提升为Object对象了
            Object obj = iterator.next();

            // 强制转换为子类
            Province province = (Province) obj;         // 不可以将Book转换为Province(存在隐藏问题)

            // 调用子类特有的功能
            province.intro();
        }
    }
}

运行结果:

在这里插入图片描述

上述代码编译时是没有什么问题,但运行时出现了类型转换异常:ClassCastException,代码存在一定的安全隐患;

1.2.2 使用泛型

  • 查看List源码:
public interface List<E> extends Collection<E> {
    boolean add(E e);
   	....
}

集合的定义者发现,无法在定义集合类时就确定该集合存储的具体类型,因此使用泛型进行占位,使用者创建集合时明确该泛型的类型;

  • 指定泛型后:
class List<Province>{ 
    boolean add(Province province);
   	....
}

Tips:在创建对象时指定泛型的类型,泛型一旦指定了具体的类型,原来泛型的占位符(E),都将变为此类型;

如何指定泛型类类型?

格式如下:

List<泛型的具体类型> list=new ArrayList();

测试类:

package com.dfbz.demo01;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo03_使用泛型来存储元素 {
    public static void main(String[] args) {

        // 创建集合,并确定好泛型(存储的类型)
        List<Province> list = new ArrayList();

        // 往集合存储对象
        list.add(new Province("甘肃", "甘|陇","西北"));
        list.add(new Province("陕西", "陕|秦","西北"));
        list.add(new Province("贵州", "贵|黔","西南"));
        list.add(new Province("云南", "云|滇","西南"));
        list.add(new Province("四川", "川|蜀","西南"));

        // 获取City类型的迭代器
        Iterator<Province> iterator = list.iterator();

        while (iterator.hasNext()){

            // 直接获取province类型
            Province province = iterator.next();

            province.intro();
        }
    }
}

1.3 泛型类

1.3.1 泛型类的使用

很明显,Collection、List、Set以及其下的子类都是泛型类,我们根据使用情况也可以定义泛型类;让泛型类的类型延迟到创建对象的时候指定;

  • 使用格式:
修饰符 class 类名<代表泛型的变量> {}

例如,API中的List接口:

class List<E>{ 
    boolean add(E e);
   	....
}

在创建对象的时候确定泛型

例如,List<String> list = new ArrayList<String>();

此时,变量E的值就是String类型,那么我们的类型就可以理解为:

public interface List<String> extends Collection<String> {
     boolean add(String e);
     ...
}

再例如,ArrayList<Integer> list = new ArrayList<Integer>();

此时,变量E的值就是Integer类型,那么我们的类型就可以理解为:

public interface List<Integer> extends Collection<Integer> {
     boolean add(Integer e);
     ...
}

举例自定义泛型类:

package com.dfbz.demo01;

public class GetClass<P> {

    // 使用泛型类型,P具体的类型还不明确,等到创建GetClass对象时再明确P的类型
    private P p;

    public P getC() {
        return p;
    }

    public void setC(P p) {
        this.p = p;
    }
}

使用:

package com.dfbz.demo01;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo04_自定义泛型类 {
    public static void main(String[] args) {
        // 创建对象,并明确泛型类型为City
        GetClass<Province> getClass = new GetClass<>();

        // setC(Province province)
        getClass.setC(new Province("新疆","新","西北"));

        // Province getC()
        Province province = getClass.getC();

        province.intro();
    }
}

1.2.2 泛型类的继承

定义一个父类,带有泛型:

public class 类名<泛型类型> {  }

例如,

package com.dfbz.demo01;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Fu<E> {
    public void show(E e) {
        System.out.println(e.toString());
    }
}

使用格式:

  • 1)定义类时确定泛型的类型

例如

package com.dfbz.demo01;

/**
 * @author lscl
 * @version 1.0
 * @intro: 在定义子类时就确定好泛型的类型
 */
public class Zi1 extends Fu<Province> {

    @Override
    public void show(Province province) {
        System.out.println("zi1: " + province);
    }
}

此时,泛型E的值就是Province类型。

  • 2)始终不确定泛型的类型,直到创建对象时,确定泛型的类型

例如

package com.dfbz.demo01;

/**
 * @author lscl
 * @version 1.0
 * @intro: 子类也变为泛型类,泛型类型具体到创建对象的时候再确定
 */
public class Zi2<P> extends Fu<P> {

    @Override
    public void show(P p) {
        System.out.println("zi2: " + p);
    }
}

确定泛型:

package com.dfbz.demo01;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo05_测试泛型类的继承 {
    public static void main(String[] args) {

        // 注意: Zi1类以及不是一个泛型类了,不能够指定泛型
//        Zi1<Book> zi1=new Zi1();          // 报错

        // 创建子类时确定泛型类型
        Zi2<Province> zi_a = new Zi2<>();
        zi_a.show(new Province("青海", "青", "西北"));


        Zi2<Book> zi_b = new Zi2<>();
        zi_b.show(new Book("《说岳全传》", "钱彩"));
    }
}

1.4 泛型方法

泛型类是在创建类时定义泛型类型,在创建对象时确定泛型类型;泛型方法则是在创建方法是定义泛型类型,在调用方法时确定泛型类型;

  • 定义格式:
修饰符 <代表泛型的变量> 返回值类型 方法名(参数){}

例如:

package com.dfbz.demo01;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class GetClassMethod {
    // 定义泛型方法
    public <P> P GetClass(P p) {
        return p;
    }
}

使用格式:调用方法时,确定泛型的类型

package com.dfbz.demo01;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo06_测试泛型方法 {
    public static void main(String[] args) {
        GetClassMethod getClassMethod = new GetClassMethod();

        // Province getClass(Province province)
        Province province = getClassMethod.GetClass(new Province("西藏", "藏", "西北"));
        province.intro();

        // Book getClass(Book book)
        Book book = getClassMethod.GetClass(new Book("《天龙八部》", "金庸"));
        book.detail();
    }
}

1.5 泛型通配符

1.5.1 通配符的使用

1)参数列表带有泛型

泛型在程序运行中全部会被擦除,我们把这种现象称为泛型擦除;但编译时期在使用泛型类进行方法传参时,不仅要匹配参数本身的类型,还要匹配泛型的类型;

Number是所有数值类的父类:

在这里插入图片描述

  • 定义一个泛型类:
package com.dfbz.泛型通配符;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class TestClass<E> {
    private E e;

    public E getE() {
        return e;
    }

    public void setE(E e) {
        this.e = e;
    }
}
  • 测试带有泛型的方法参数列表:
package com.dfbz.泛型通配符;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo01_方法参数带有泛型的问题 {
    public static void main(String[] args) {

        TestClass<Number> t1 = new TestClass<>();
        test1(t1);

        TestClass<Integer> t2 = new TestClass<>();
        // 符合方法的参数类型(TestClass),但不符合泛型类型(Number),编译报错
//        test1(t2);
    }

    public static void test1(TestClass<Number> testClass) {
        // 可以获取具体的泛型对象
        Number number = testClass.getE();
        System.out.println("test1...");
    }

    /*
     和上面的方法冲突了,因为泛型在运行期间会被擦除
     相当于: public static void test1(TestClass testClass)
     */

/*
    public static void test1(TestClass<Integer> testClass) {
        System.out.println("test1...");
    }
*/

}

2)泛型通配符

泛型的通配符:不知道使用什么类型来接收的时候,此时可以使用?,?表示未知通配符。

  • 示例:
package com.dfbz.泛型通配符;

import com.dfbz.demo01.Book;
import com.dfbz.demo01.Province;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo02_泛型通配符的使用 {
    public static void main(String[] args) {
        TestClass<String> t1 = new TestClass<>();
        test1(t1);

        TestClass<Integer> t2 = new TestClass<>();
        test1(t2);

        TestClass<Number> t3 = new TestClass<>();
        test1(t3);

        TestClass<Province> t4 = new TestClass<>();
        test1(t4);

        TestClass<Book> t5 = new TestClass<>();
        test1(t5);
    }

    // ?: 代表可以接收任意泛型
    public static void test1(TestClass<?> testClass) {
        
        // 被?接收的泛型都将提升为Object
        Object obj = testClass.getE();
        System.out.println("test1...");
    }
}

Tips:需要注意的是,被<?>接收过的类型都将提升为Object类型;

1.5.2 泛型上下边界

利用泛型通配符?可以接收任意泛型,但是随之而然带来一个问题,就是所有类型都提升为Object;范围太广了,使用起来非常不方便,因此为了让泛型也可以利用多态的特点,泛型的上下边界的概念由此引出;

利用泛型的通配符可以指定泛型的边界;

泛型的上限

  • 格式: 类型名称 <? extends 类> 对象名称
  • 含义: 只能接收该类型及其子类
  • 功能: 在使用时,可以使用上边界类来接收泛型类型。因为能够传递进来的都是上边界的子类;因此可以使用上边界类来接收泛型类型;

泛型的下限

  • 格式: 类型名称 <? super 类> 对象名称
  • 含义: 只能接收该类型及其父类型
  • 功能: 在使用时,只能使用Object类型来接收泛型类型。因为传递进来的必定是下边界的父类,而下边界的父类可以有N多个,因此只能使用Object来接收泛型类型;

可以看到基本数据类型的包装类都是继承与Number类;

  • 测试泛型上下边界:
package com.dfbz.泛型通配符;

import java.util.ArrayList;
import java.util.Collection;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Demo03_泛型的上下边界 {
    public static void main(String[] args) {

        List<A> list1 = new ArrayList();
        List<B> list2 = new ArrayList();
        List<C> list3 = new ArrayList();
        List<Object> list4 = new ArrayList();

//        method1(list1);               // 不能
//        method1(list2);               // 能
//        method1(list3);               // 能
//        method1(list4);               // 不能

//        method2(list1);               // 能
//        method2(list2);               // 能
//        method2(list3);               // 不能
//        method2(list4);               // 能
    }

    public static void method1(List<? extends B> list) {

        // 上边界的好处: 可以使用上边界的对象
        for (B b : list) {
            System.out.println(b);
        }
    }

    public static void method2(List<? super B> list) {

        // 下边界则必须使用Object来接收
        for (Object obj : list) {
            System.out.println(obj);
        }
    }
}
class A {
}

class B extends A {
}

class C extends B {
}

1.6 泛型的擦除

Java的泛型基本上都是在编译器这个层次上实现的,在生成的字节码中是不包含泛型中的类型信息的,使用泛型的时候加上类型参数,在编译器编译的时候会去掉,这个过程称为类型擦除。

1.6.1 限制擦除

泛型在擦除过程中有限制擦除无限制擦除

  • 有限制擦除:

在这里插入图片描述

  • 无限制擦除:将泛型类型提升为Object类型

在这里插入图片描述

1.6.2 泛型的桥接方法

在接口使用泛型时,在运行期间接口中的泛型也一样会被擦除;

在这里插入图片描述

那如果编写了实现类来实现这个泛型接口,实现类中的泛型在运行期间也会被擦除,这样一来就会出现接口的方法并没有在实现类中得到实现:

在这里插入图片描述

好在JVM进行了特殊处理,如果我们编写的类实现了一个带有泛型的接口时,在运行期期间JVM会在实现类中帮我们自动的生产一个方法来帮助我们实现泛型接口中被擦除过后的那个方法,这个方法被称为桥接方法

  • 如图所示:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/384774.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

只知道ChatGPT?这些AI工具同样值得收藏

B站|公众号&#xff1a;啥都会一点的研究生 人工智能革命带来了许多能够提高生产力和转变工作方式的工具&#xff0c;本期将重点介绍音频、视频、设计以及图像和数据清理中的顶级 AI 工具。 音视频类AI工具&#xff1a; VoicePen AI https://voicepen.ai&#xff1a;该工具可…

【内网服务通过跳板机和公网通信】花生壳内网穿透+Nginx内网转发+mqtt服务搭建

问题&#xff1a;服务不能暴露公网 客户的主机不能连外网&#xff0c;服务MQTT服务部署在内网。记做&#xff1a;p1 (computer 1)堡垒机&#xff08;跳板机&#xff09;可以连外网&#xff0c;内网IP 和 MQTT服务在同一个网段。记做&#xff1a;p2 (computer 2)对他人而言&…

linux 中的log

linux 中的log 由于内核的特殊性&#xff0c;我们不能使用常规的方法查看内核的信息。下面介绍几种方法。 1 printk()打印内核消息。 2 管理内核内存的daemon&#xff08;守护进程&#xff09; Linux系统当中最流行的日志记录器是Sysklogd&#xff0c;Sysklogd 日志记录器由…

【C++】位图

文章目录位图概念位图操作位图代码位图应用位图概念 boss直接登场&#xff1a; 给40亿个不重复的无符号整数&#xff0c;没排过序。给一个无符号整数&#xff0c;如何快速判断一个数是否在这40亿个数中❓ 40亿个整数&#xff0c;大概就是16GB。40亿个字节大概就是4GB。 1Byt…

sklearn中的降维算法PCA和SVD

目录 一.维度 二.sklearn中的降维算法 三.PCA与SVD 四.降维的实现 五.重要参数n_components 1.累积可解释方差贡献率曲线选择n_components 2.最大似然估计自选超参数 3.按信息量占比选超参数 六.PCA中的SVD 七.重要参数svd_solver 与 random_state 八.重要属性compon…

FormData同时传输多个文件和其他数据

近日有个需求是&#xff1a;在web的对话框中&#xff0c;用户可以输入文本内容和上传附件&#xff0c;附件的数量不限&#xff0c;所有附件总和大小不超过20M。 这个实现的方法不止一种&#xff0c;比如之前的后端同事是要求&#xff1a;文件和文本分开传输&#xff0c;文件用…

程序员的上帝视角(2)——我所体悟的思维方式

心外无物仍然记得在高中阶段&#xff0c;总是为了没有解题思路而苦恼。现在回想起来&#xff0c;总算有点感悟——执着于做题、刷题&#xff0c;却忽视了最本质的思考&#xff0c;为什么可以有这样的解题思路&#xff0c;别人是如何想到这种解题思路的。这正是心学所提倡的&…

189、【动态规划】leetcode ——312. 戳气球(C++版本)

题目描述 原题链接&#xff1a;312. 戳气球 解题思路 &#xff08;1&#xff09;回溯法 很多求最值实际上就是穷举所有情况&#xff0c;对比找出最值。因为不同的戳气球顺序会产生不一样的结果&#xff0c;所以实际上这就是一个全排列问题。 class Solution { public:int r…

linux shell 入门学习笔记18 函数开发

概念 函数就是将你需要执行的shell命令组合起来&#xff0c;组成一个函数体。一个完整的函数包括函数头和函数体&#xff0c;其中函数名就是函数的名字。 优点 将相同的程序&#xff0c;定义&#xff0c;封装为一个函数&#xff0c;能减少程序的代码数量&#xff0c;提高开发…

新:DlhSoft Gantt Chart for WPF Crack

用于 Silverlight/WPF 4.3.48 的 DlhSoft 甘特图灯光库 改进甘特图、网络图和 PERT 图表组件的 PERT 关键路径算法。2023 年 3 月 2 日 - 17:09新版本特征 改进了甘特图、网络图和 PERT 图表组件的 PERT 关键路径算法。Silverlight/WPF 标准版的 DlhSoft 甘特图灯光库 DlhSoft …

精选博客系列|面向公共安全的SD-WAN Edge:刷新VMware边缘计算栈

在巴塞罗那举行的 2023 世界移动通信大会上&#xff0c;VMware 展台展示了配备小型加固 SD-WAN 设备、搭配用于自动车牌识别等应用的 Jenoptik 软件的特斯拉汽车。VMware SD-WAN 能够在车队中创建移动办公室&#xff0c;实现安全的移动通信和实时边缘计算。 萨里和苏塞克斯警方…

如何做好固定资产管理?易点易动高能解决方案来了

企业固定资产管理一直以来都是企业开源节流的重中之重。在当前的数字化时代中&#xff0c;固定资产需要数字化支撑&#xff0c;实现固定资产的有序、科学管理&#xff0c;以便尽可能实现物尽其用&#xff0c;让处于高速发展期中的企业节约在固定资产上的投入成本。 如何做好固…

B站的多个视频教程,怎样生成一个二维码?

商业插画视频教程、电商运营视频教程、在线网课视频、舞蹈视频教程、摄影视频教程、语言学习教程、纪录片视频…所有你发布在哔哩哔哩上的视频&#xff0c;都可以放在一个二维码里面。 任何人只要扫描这个二维码&#xff0c;就能在线观看你的这些视频教程&#xff01;分享起来…

渗透测试之地基服务篇:无线攻防之钓鱼无线攻击(上)

简介 渗透测试-地基篇 该篇章目的是重新牢固地基&#xff0c;加强每日训练操作的笔记&#xff0c;在记录地基笔记中会有很多跳跃性思维的操作和方式方法&#xff0c;望大家能共同加油学到东西。 请注意 &#xff1a; 本文仅用于技术讨论与研究&#xff0c;对于所有笔记中复现…

【Spring6】| Bean的作用域

目录 一&#xff1a;Bean的作用域 1. singleton&#xff08;单例&#xff09; 2. prototype&#xff08;多例&#xff09; 3. 其它scope 4. 自定义scop&#xff08;了解&#xff09; 一&#xff1a;Bean的作用域 1. singleton&#xff08;单例&#xff09; &#xff08;1…

【机器学习】TP TN FP FN及IoU的关系

TP&#xff08;True Positives&#xff09;&#xff1a; 真的正样本 【正样本 被正确分为 正样本】TN&#xff08;True Negatives&#xff09;&#xff1a; 真的负样本 【负样本 被正确分为 负样本】FP&#xff08;False Positives&#xff09;&#xff1a; 假的正样本 【负…

我做测试的3次能力飞跃,让我直接进了字节

回顾我从小公司到字节的成长路径&#xff0c;基本上是伴随着“3次能力飞跃”实现的。 第一家入职的时候是一家小公司&#xff0c;当然我也想直接去字节&#xff0c;可惜自己能力不足。 刚开始入行的时候&#xff0c;什么也不懂&#xff0c;就是从最简单的手工测试做起。每天做…

想开发IM集群?先搞懂什么是RPC!

即时通讯网官方技术群和社区里&#xff0c;经常有开发者在纠结怎么开发IM集群&#xff0c;虽然真正的使用人数&#xff0c;可能用个人电脑单机都能支撑。你也许会说&#xff0c;明明不需要用到IM集群&#xff0c;干吗要自找麻烦&#xff1f;答曰&#xff1a;“老板说这个得有&a…

I.MX6ULL内核开发0:linux内核模块

目录 简要 一、内核模块的概念 二、内核模块加载、卸载过程 简要 1、内核模块的概念 2、内核模块的原理&#xff1a;内核模块在内核的加载、卸载过程。 一、内核模块的概念 内核&#xff0c;是一个操作系统的核心。是基于硬件的第一层软件扩充&#xff0c;提供操作系统的最…

Prim和Kruskal的区别?哪个好?

Prim和Kruskal有啥区别&#xff1f;到底哪个好&#xff1f; 今天做了一道最小生成树的题&#xff0c;发现了一点猫腻&#xff01; 题目在这里 &#xff1a; 《修路问题1》 文章目录Prim和Kruskal有啥区别&#xff1f;到底哪个好&#xff1f;先说结论PrimKruskal修路问题1——…