面试官:什么是泛型擦除、泛型上界、泛型下界、PECS原则?

news2024/11/27 10:42:22

尼恩说在前面

在40岁老架构师 尼恩的读者交流群(50+)中,最近有小伙伴拿到了一线互联网企业如阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格,遇到很多很重要的面试题:

问题1:什么是PECS原则? 说说具体怎么用?

问题2:什么是 泛型擦除? 说说原理?

问题3:什么是泛型上界? 什么是泛型下界?

最近又有小伙伴在面试美团,遇到了相关的面试题。

很多小伙伴说,自己对什么PECS 原则,可以说一脸懵逼,面试官不满意,面试挂了。

借着此文,尼恩给大家做一下系统化、体系化的梳理,使得大家内力猛增,展示一下雄厚的 “技术肌肉、技术实力”,让面试官爱到 “不能自已、口水直流”,然后实现”offer直提,offer自由”。

当然,这道面试题,以及参考答案,也会收入咱们的 《尼恩Java面试宝典PDF》V162版本,供后面的小伙伴参考,提升大家的 3高 架构、设计、开发水平。

《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》的PDF,请到文末公号【技术自由圈】取

文章目录

    • 尼恩说在前面
    • 什么是泛型
    • 泛型定义:泛型类、泛型接口、泛型方法
    • 为啥不用Object做泛型化?
    • 泛型的两大好处
    • 泛型的上界/ 上界通配符(Upper Bounds Wildcards)
      • 上界通配符(Upper Bounds Wildcards)的问题
    • 泛型的下界/ 下界通配符(Lower Bounds Wildcards)
      • 下界/ 下界通配符(Lower Bounds Wildcards)的问题
    • PECS原则
      • 1. Producer Extends 上界生产
      • 2. Consumer Super 下界消费,就是消费者使用 “? super T”通配符
    • 泛型的类型擦除
      • 无界泛型擦除
      • 上界擦除
      • 下界擦除
    • 说在最后:老马识途,有问题找老架构求助
    • 尼恩技术圣经系列PDF

首先,从Java的泛型说起。

什么是泛型

泛型的本质是 类型参数化,解决类型爆炸的问题。

所谓泛型是指将类型参数化,以达到代码复用提高软件开发工作效率的一种数据类型。

比如: 如果我们的代码中存在很多的 食物类型, 继承关系如下

然后我们要定义一个盘子 plate,注意这个盘子除了 装入食物food之外,还可以装其他的比如 小玩具。

为了装不同类型的食物,我们需要定义不同的盘子:

1) 装水果的盘子  FruitPlate2) 装肉的盘子  MeatPlate3) 装苹果的盘子  ApplePlate4) 装香蕉的盘子  BananaPlate

.....N) 装云南苹果的盘子  YunnanFruitPlate

这就是盘子类型的 类型爆炸。

如何解决上面的类型爆炸问题呢? 这就要用到泛型。

那么盘子里的东西的类型,我们就用泛型

//盘子里的东西
private T someThing;

从这个例子看到:泛型是一种类型占位符,或称之为类型参数

如何使用呢?

public static void main(String[] args) {

    //创建一个装肉的盘子
    PlateDemo1<Meat> plateDemo1 =new PlateDemo1<>(new Pork());

    //创建一个装水果的盘子
    PlateDemo1<Fruit> plateDemo2 =new PlateDemo1<>(new Apple());

}

所谓泛型,就是 数据类型 指定为一个参数,在不创建新类的情况下,通过创建变量的时候去确定 数据的具体类型。

也就是说,在创建对象或者调用方法的时候才明确下具体的类型。

泛型定义:泛型类、泛型接口、泛型方法

泛型定义格式:

<类型>:指定一种类型的格式,这里的类型可以看做是形参

<类型1,类型2…>:指定多种类型的格式,多种类型之间用逗号隔开。定义的时候是泛型形参

这个泛型形参,将来具体调用时候,需要有给定的类型,那个给定的具体的Java类型可以看出是实参。

泛型可以在类、接口、方法中使用,分别称为泛型类、泛型接口、泛型方法。

第一类:泛型类
定义格式:

修饰符 class 类名<类型> { }

上面的例子就是 泛型类

//盘子,可以装 任何东西,包括 食物 其他
class PlateDemo1<T> {

    //盘子里的东西
    private T someThing;
}

第二类:泛型方法

定义格式:

修饰符 <泛型类型> 返回值类型 方法名(类型 变量名) { }

示例代码:

public <T> void demo(T t) { 
    ...
} 

第三类:泛型接口

定义格式:

修饰符 interface 接口名<类型> { }

示例代码:

public interface Generic<T> { 
    void demo(T t); 
}

泛型接口的实现类

public class GenericImpl<T> implements Generic<T> { 
    public void demo(T t) { 
      ...
    } 
}

为啥不用Object做泛型化?

没有泛型的情况的下,好像Object也能实现简单的 泛化。

通过定义为类型Object的引用,来实现参数的“任意化”。

比如上面的例子的 泛型类

//盘子,可以装 任何东西,包括 食物 其他
class PlateDemo1<T> {

    //盘子里的东西
    private T someThing;
}

通过定义为类型Object的引用,来实现参数的“任意化”,结果如下

//盘子,可以装 任何东西,包括 食物 其他
class PlateDemo1   {

    //盘子里的东西
    private Object  someThing;
}

Object实现参数的 “泛型化”、“任意化”带来的缺点是:要做显式的强制类型转换。

参数类型强制转换有一个大大降低代码复用性和扩展性的坏处:

  • 首先,要求开发者对实际参数类型可预知。
  • 其次,不利于未来的 扩展。

泛型的两大好处

而引入泛型后,有如下好处:

1、避免了强制类型转换,提高代码的复用性和扩展性

泛型中,所有的类型转换都是自动和隐式的,不需要强制类型转换,可以提高代码的重用率,再加上明确的类型信息,代码的可读性也会更好。

2、把运行时期的问题提前到了编译期,编译时的类型检查,使程序更加健壮

使用普通的Object泛化,对于强制类型转换错误的情况,编译期不会提示错误,在运行的时候才出现异常,这是一个安全隐患。

泛型的好处是在编译期检查类型安全,并能捕捉类型不匹配的错误,避免运行时抛出类型转化异常ClassCastException,将运行时错误提前到编译时错误,消除安全隐患。

正是由于以上两点原因,泛型得到了广泛的应用。

比如Java中,所有的标准集合接口都是泛型化的:Collection<V>List<V>Set<V>Map<K,V>

泛型的上界/ 上界通配符(Upper Bounds Wildcards)

现在我定义一个“水果盘子”,用来装苹果, 逻辑上水果盘子当然可以装苹果。

那么,一个“装苹果的盘子”,能转换成一个“装水果的盘子”吗?

看下面的例子

那么,一个“装苹果的盘子”,能转换成一个“装水果的盘子”吗? 答案是不行的。

编译器 的逻辑是这样的:

  • 苹果 is-a 水果
  • 装苹果的盘子 not is-a 装水果的盘子

也就是说:就算 苹果 is-a 水果,但容器之间是没有继承关系的。

怎么办?这里用到了 泛型上界。 泛型上界是这么定义的:

<?extends 基类B> 

<?extends 基类B> 表示泛型实参类型的上界是“基类B”,

换句话说,泛型实参的类型,可能是“基类B” 或者是“基类B”的子类;

修改之后的例子如下,使用 泛型上界通配符(Upper Bounds Wildcards)后,编译器就不报错误了:

使用(Upper Bounds Wildcards)通配符作为泛型实参,所定义 PlateDemo1<? extends Fruit> 引用,可以 覆盖下图中方框内部的所有子类的 泛型对象。

<?extends T> 表示类型的上界,参数化类型可能是T 或者是 T的子类;

PlateDemo1<? extends Fruit> 引用,可以 覆盖下图中方框内部的所有子类的 泛型对象,编译器都不报错,下面的代码如下:

为啥<? extends Fruit> 叫做 上界,而不叫下届? 原因是: 这个通配符,定义了实参的类型上限 为 Fruit,具体如下图:

上界通配符(Upper Bounds Wildcards)的问题

上界通配符(Upper Bounds Wildcards)的作用,实现了 子类泛型对象 到 父类Java泛型对象之间的引用转换。

但是,这样的引用转换也有一定的副作用。

具体如下:

通过例子可以看到:

(1)往基类盘子,set( ) 任何对象,都 失效了

(2)从基类盘子,get ( ) 对象的引用,返回 类型是上界对象, 这个还是 可以的

简单来说: 上界<? extends T>不能往里存,只能往外取

所以,上界通配符(Upper Bounds Wildcards)什么时候用,什么时候不用呢:

(1)当从集合中获取元素进行操作的时候用,可以用当前元素的类型接收,也可以用当前元素的父类型接收。

(2)往集合中添加元素时,不能用上界通配符(Upper Bounds Wildcards)。

泛型的下界/ 下界通配符(Lower Bounds Wildcards)

往集合中添加元素时,不能用上界通配符(Upper Bounds Wildcards)。

怎么办呢? Java也提供了一种通配符,叫做 泛型的下界/ 下界通配符(Lower Bounds Wildcards)。

泛型上界是这么定义的:

<super 子类C> 

<?super 子类C> 表示泛型实参类型的下界是“子类C”,

<? super T> 表示 T是类型下边界,参数化类型是此T类型的超类型,直至object;

尼恩认为下面的这一张图,下界的感觉更加强烈一些:

下界/ 下界通配符(Lower Bounds Wildcards)的问题

下界/ 下界通配符(Lower Bounds Wildcards) 作用,实现了 复类泛型对象 到 子类Java泛型对象之间的引用转换。

但是,这样的引用转换也有一定的副作用。

具体如下:

通过例子可以看到:

(1)往基类盘子,set( ) 任何子类对象,都是OK的

(2)从基类盘子,get ( ) 对象的引用是编译错误的,除非是Object类型

简单来说:下界<? super T>可以往里存,但不能向外取,要取只能取Object对象

所以,下界/ 下界通配符(Lower Bounds Wildcards)什么时候用,什么时候不用呢:

(1)当往集合中添加元素时候用,既可以添加T类型对象,又可以添加T的子类型对象

(2)当从集合get ( ) 对象的引用时,不能用上界通配符(Upper Bounds Wildcards)。除非get 的是Object类型

PECS原则

PECS原则的全称是Producer Extends Consumer Super,很多小伙伴从没听说过,面试的时候,只要面试官一问,大部分都是一脸懵逼。

什么是PECS(Producer Extends Consumer Super)原则?PECS原则全称"Producer Extends, Consumer Super",即上界生产,下界消费。

  • Producer Extends 上界生产,就是 生产者使用 “? extends T”通配符。

  • Consumer Super 下界消费,就是消费者使用 “? super T”通配符

最终PECS (Producer Extends Consumer Super ) 原则

  • 频繁往外读取内容的,适合用上界Extends。
  • 经常往里插入的,适合用下界Super。

在阿里编程规范中,就有这么一条:

【强制】泛型通配符<? extends T>来接收返回的数据,此写法的泛型集合不能使用 add 方法, 而<? super T>不能使用 get 方法,两者在接口调用赋值的场景中容易出错。

1. Producer Extends 上界生产

Producer Extends 上界生产,就是 生产者使用 “? extends T”通配符。

以“? extends T”声明的集合,不能往此集合中添加元素,所以它也只能作为生产者,如下:

所以,使用 “? extends T” 上界,能轻松地成为 producer 生产者,完成

  • 读取元素

  • 迭代元素

这就是 Producer Extends 上界生产,就是 生产者使用 “? extends T”通配符。

2. Consumer Super 下界消费,就是消费者使用 “? super T”通配符

在通配符的表达式中,只有“? super T”能添加元素,所以它能作为消费者(消费其他通配符集合)。

当然,针对采用“? super T”通配符的集合,对其遍历时需要多一次转型。

总之 PECS就是:

1、频繁往外读取内容的,适合用上界Extends。

2、经常往里插入的,适合用下界Super

明白了泛型、泛型的上界,泛型的下届之后, 尼恩带大家来回答这个面试的核心问题: 什么是泛型的擦除。

泛型的类型擦除

前面讲到,泛型的本质是 类型参数化,解决类型爆炸的问题。比如: 如果我们的代码中存在很多的 食物类型, 继承关系如下

没有泛型,为了实现去装不同类型的食物,我们需要定义不同的盘子:

1) 装水果的盘子  FruitPlate2) 装肉的盘子  MeatPlate3) 装苹果的盘子  ApplePlate4) 装香蕉的盘子  BananaPlate

.....N) 装云南苹果的盘子  YunnanFruitPlate

如何解决上面的类型爆炸问题呢? 这就要用到泛型。

而使用泛型,我们定义一个就可以了:

//盘子,可以装 任何东西,包括 食物 其他
class PlateDemo1<T> {

    //盘子里的东西
    private T someThing;

    public PlateDemo1(T t) {
        someThing = t;
    }
    ....
}

这样,就避免 了 盘子类型的 类型爆炸。尤其在Java中的集合类,如果不用泛型,不知道要定义多少的具体集合类。

那么 Java中的泛型,有一个 类型擦除 的特点:

  • java的泛型,只在编译期有效。

  • 编译之后的字节码,已经抹除了泛型信息。

所谓的类型擦除(type erasure),指的是泛型只在编译时起作用,在进入JVM之前,泛型会被擦除掉,根据泛型定义的形式而被替换为相应的类型。这也说明了Java的泛型其实是伪泛型。

类型擦除简单来说,泛型类型在逻辑上可以看成是多个不同的类型,实际上都是相同类型。

比如:

Food food = new Fruit(); // 没问题
ArrayList<Food> list= new ArrayList<Fruit>(); // 报错

或者说下面的ArrayList ,在逻辑上看,可以看成是多个不同的类型,实际上都是相同类型

ArrayList<Food> list1
ArrayList<Fruit> list2
ArrayList<Apple> list3
.....

泛型类型在逻辑上可以看成是多个不同的类型,但实际上都是相同的类型。

看下面的例子

类型参数在运行中并不存在,这意味着:

  • 运行期间,泛型不会添加任何的类型信息;
  • 不能依靠泛型参数,进行类型转换。

Java泛型的实现是靠类型擦除技术实现的,类型擦除是在编译期完成的,泛型擦除怎么做呢?

  • 在编译期,编译器会将泛型的类型参数都擦除成它指定的原始限定类型
  • 如果没有指定的原始限定类型则擦除为Object类型,之后在获取的时候再强制类型转换为对应的类型,
  • 因此生成的Java字节码中是不包含泛型中的类型信息的,即运行期间并没有泛型的任何信息。

无界泛型擦除

当泛型类型被声明为一个具体的泛型标识,或一个无界通配符时,泛型类型将会被替代为Object

这也比较容易理解,如 List<?>,PlateDemo1<?>, 当获取元素的时,因为不能够确定具体的类型,所以只能使用Object来接收,

在擦除的时候也是一样的道理,无法确定具体类型,所以擦除泛型时会将其替换为Object类型,如:

上界擦除

当泛型类型被声明为一个上界通配符时,泛型类型将会被替代为相应上界的类型。

主要,这里的上界,指的是用于类型定义场景里边的上界:

而不是变量定义场景里边用到到泛型上界,如下:

 List<? extends Fruit> producer =...;

用泛型上界定义class的时候,指的是用于类型定义,泛型类型将会被替代为相应上界的类型。

下界擦除

下界通配符的擦除,同无界通配符

下届只能定义引用的时候用,在定义类型的时候用不了,所以下界擦除只能替换为Object

下界擦除只能替换为Object

说在最后:老马识途,有问题找老架构求助

以上的内容,如果大家能对答如流,如数家珍,基本上 面试官会被你 震惊到、吸引到。

最终,让面试官爱到 “不能自已、口水直流”。 offer, 也就来了。

其实, “offer自由” 不难实现, 前段时间一个跟尼恩卷了2年的武汉小伙,9年经验, 在年底大裁员的极度严寒/痛苦被裁的背景下, offer拿到手软, 实现真正的 “offer自由” 。

在面试之前,建议大家系统化的刷一波 5000页《尼恩Java面试宝典PDF》,里边有大量的大厂真题、面试难题、架构难题。很多小伙伴刷完后, 吊打面试官, 大厂横着走

在刷题过程中,如果有啥问题,大家可以来 找 40岁老架构师尼恩交流。

尼恩一直深耕技术,不是在研究技术,就是在研究技术的路上,加尼恩微信之后不一定立马通过, 但是,最多1-2小时就会审核的。

深研技术,远离浮躁。作为资深技术人,尼恩实在太忙了…

特别要说的是:很多小伙伴简历投出去后如泥牛入海、不冒一泡、没有面试机会。

遇到这种难题,可以找尼恩来改简历、做帮扶。

另外,遇到架构升级、晋升受阻、职业打击等职业难题,也可以找尼恩取经, 可以省去太多的折腾,省去太多的弯路。

尼恩已经指导了大量的小伙伴上岸,前段时间指导一个40岁+被裁小伙伴上岸,拿到了一个年薪100W的offer。

尼恩技术圣经系列PDF

  • 《NIO圣经:一次穿透NIO、Selector、Epoll底层原理》
  • 《Docker圣经:大白话说Docker底层原理,6W字实现Docker自由》
  • 《K8S学习圣经:大白话说K8S底层原理,14W字实现K8S自由》
  • 《SpringCloud Alibaba 学习圣经,10万字实现SpringCloud 自由》
  • 《大数据HBase学习圣经:一本书实现HBase学习自由》
  • 《大数据Flink学习圣经:一本书实现大数据Flink自由》
  • 《响应式圣经:10W字,实现Spring响应式编程自由》
  • 《Go学习圣经:Go语言实现高并发CRUD业务开发》

……完整版尼恩技术圣经PDF集群,请找尼恩领取

《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》PDF,请到下面公号【技术自由圈】取↓↓↓

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

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

相关文章

回溯法:回溯法通用模版以及模版应用

从一个问题开始 给定两个整数 n 和 k&#xff0c;返回 1 ... n 中所有可能的 k 个数的组合。 示例: 输入: n 4, k 2 输出: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4] ] 很容易想到 用两个for循环就可以解决。 如果n为100&#xff0c;k为50呢&#xff0c;那就50层for循…

文字的baseLine算法

使用canvas的drawText方法时候&#xff0c;除了要传入画笔和text还需要传入一个x坐标和y坐标。这边的x和y坐标是Baseline的坐标。 public void drawText(NonNull String text, float x, float y, NonNull Paint paint) {super.drawText(text, x, y, paint);} top:是 baseLine到…

微信小程序之WXML 模板语法之数据绑定、事件绑定、wx:if和列表渲染

学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。各位小伙伴&#xff0c;如果您&#xff1a; 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持&#xff0c;想组团高效学习… 想写博客但无从下手&#xff0c;急需…

消息中间件之Kafka(二)

1.Kafka线上常见问题 1.1 为什么要对topic下数据进行分区存储? 1.commit log文件会受到所在机器的文件系统大小的限制&#xff0c;分区之后可以将不同的分区放在不同的机器上&#xff0c; 相当于对数据做了分布式存储&#xff0c;理论上一个topic可以处理任意数量的数据2.提…

OpenHarmony 应用开发入门 (二、应用程序包结构理解及Ability的跳转,与Android的对比)

在进行应用开发前&#xff0c;对程序的目录及包结构的理解是有必要的。如果之前有过android开发经验的&#xff0c;会发现OpenHarmony的应用开发也很简单&#xff0c;有很多概念是相似的。下面对比android分析总结下鸿蒙的应用程序包结构&#xff0c;以及鸿蒙对比android的诸多…

【报错】Arco新建工程时 Error: spawnSync pnpm.cmd ENOENT

文章目录 安装环境开始安装选择技术栈选择pro项目遇到的问题 安装步骤&#xff1a;https://arco.design/vue/docs/pro/start 安装环境 npm i -g arco-cli开始安装 arco init hello-arco-pro选择技术栈 ? 请选择你希望使用的技术栈React❯ Vue选择pro项目 ? 请选择一个分类业…

智谱AI发布新一代国产文本生成模型:GLM-4,“宣称”性能逼近GPT-4 (怎么又是GPT )

希望别又是一个只顾着跑分数不注重性能的东西。。。 智谱AI GLM-4介绍体验网址链接&#xff1a;智谱AI开放平台 更多消息&#xff1a;AI人工智能行业动态&#xff0c;aigc应用领域资讯 智谱AI是一家专注于人工智能技术研发和应用的公司&#xff0c;致力于打造全球领先的大模型…

2024年美赛数学建模思路 - 案例:感知机原理剖析及实现

文章目录 1 感知机的直观理解2 感知机的数学角度3 代码实现 4 建模资料 # 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 感知机的直观理解 感知机应该属于机器学习算法中最简单的一种算法&#xff0c;其…

第二课:BERT

文章目录 第二课&#xff1a;BERT1、学习总结&#xff1a;为什么要学习BERT&#xff1f;预训练模型的发展历程BERT结构BERT 输入BERT EmbeddingBERT 模型构建BERT self-attention 层BERT self-attention 输出层BERT feed-forward 层BERT 最后的Add&NormBERT EncoderBERT 输…

深入剖析 Git 对象底层原理

一、引言 在我们日常使用 Git 时&#xff0c;通常的操作是&#xff1a; 在写完一段代码后&#xff0c;执行 git add命令&#xff0c;将这段代码添加到暂存区中然后再执行 git commit和 git push 命令&#xff0c;将 本地 Git 版本库中的提交同步到服务器中的版本库中 Git 在…

phpStorm 设置终端为git bash

环境&#xff1a; windows , PhpStorm 2022 为自己的终端配置git样式的使用&#xff0c; 默认终端样式 一、打开设置&#xff0c;选择git bin 二、重新打开终端 不加--login -i 的终端 加了--login -i 的终端 最重要的一点是什么&#xff0c;他可以像mac一样支持 ctrlv 复…

【学习记录】Ouster雷达运行fastlio提示 Failed to find match for field ‘ring‘ 的解决办法

本文仅用于个人记录。 在使用ouster雷达运行fastlio代码时&#xff0c;提示 Failed to find match for field ‘ring’ 但ouster雷达确实是发布了ring信息&#xff0c;可以从启动的rviz里面看到包括ring。 进一步检查&#xff0c;发现ouster对ring的定义是 uint_16t&#xf…

Redis: Redis介绍

文章目录 一、redis介绍二、通用的命令三、数据结构1、字符串类型&#xff08;String&#xff09;&#xff08;1&#xff09;介绍&#xff08;2&#xff09;常用命令&#xff08;3&#xff09;数据结构 2、列表&#xff08;List&#xff09;&#xff08;1&#xff09;介绍&…

【Linux的权限命令详解】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 shell命令以及运行原理 Linux权限的概念 Linux权限管理 一、什么是权限&#xff1f; 二、权限的本质 三、Linux中的用户 四、linux中文件的权限 4.1、文件访问…

Minio文件分片上传实现

资源准备 MacM1Pro 安装Parallels19.1.0请参考 https://blog.csdn.net/qq_41594280/article/details/135420241 MacM1Pro Parallels安装CentOS7.9请参考 https://blog.csdn.net/qq_41594280/article/details/135420461 部署Minio和整合SpringBoot请参考 https://blog.csdn.net/…

BlueBunny:基于低功耗蓝牙的Bash bunny命令控制C2框架

关于BlueBunny BlueBunny是一款功能强大的命令控制框架&#xff0c;该工具基于低功耗蓝牙实现数据通信&#xff0c;可以帮助广大研究人员直接通过蓝牙将控制指令发送给Bash Bunny。 什么是Bash Bunny Bash Bunny是一款类似于USB Rubber Ducky的多功能USB攻击工具&#xff08;…

认识并使用LlamaIndex

认识并使用LlamaIndex 一、认识LlamaIndex1、是什么2、为什么要搞Llama Index&#xff1f;3、怎么搞Llama Index&#xff1f;3.1 方案1&#xff1a;用你的数据对LLM进行微调&#xff08;fine-tune&#xff09;3.2 方案2&#xff1a;[检索增强生成&#xff08;RAG&#xff09;](…

实验六 模式对象管理与安全管理

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的很重要&…

ChatGPT 到 Word:使用 Writage 进行复制粘贴魔法

ChatGPT 到 Word&#xff1a;使用 Writage 进行复制粘贴魔法 写在前面Writage的使用 写在前面 随着ChatGPT的日益普及&#xff0c;越来越多的人每天依赖它来完成各种任务。无论是寻找信息、语言翻译、解决数学问题&#xff0c;还是精炼复杂的概念和文本&#xff0c;ChatGPT 都…

Redis 存在线程安全问题吗?为什么?

一个工作了 5 年的粉丝私信我。 他说自己准备了半年时间&#xff0c;想如蚂蚁金服&#xff0c;结果第一面就挂了&#xff0c;非常难过。 问题是&#xff1a; “Redis 存在线程安全问题吗&#xff1f;” 一、问题解析 关于这个问题&#xff0c;我从两个方面来回答。 第一个&a…