【iOS】—— block,KVC,KVO,Category等问题解答

news2024/11/27 14:37:58

文章目录

  • block
    • 1.block的原理是怎样的?本质是什么?
    • 2.__block的作用是什么?有什么使用注意点?
    • 3.block的属性修饰词为什么是copy?使用block有哪些使用注意?
    • 4.block在修改NSMutableArray,需不需要添加__block?
    • 5.关于block对不同种变量的捕获问题
      • 局部变量:
      • 全局变量
      • 静态全局变量
      • 静态局部变量
    • 6.block捕获变量的原理是什么?
    • 7.__block修饰符的作用
  • KVO
    • 1.iOS用什么方式实现对一个对象的KVO?(KVO的本质是什么?)
      • 总结
    • 2.如何手动触发KVO?
    • 3.直接修改成员变量会触发KVO么?
  • KVC
    • 1.通过KVC修改属性会触发KVO么?
    • 2.KVC的赋值和取值的过程是怎样的?原理是什么?
      • 赋值:KVC赋值(setValue:forKey:)
      • 取值:KVC取值(valueForKey:)
  • Category
    • 1.Category的使用场合是什么?
    • 2.Category的实现原理
    • 3.Category和Class Extension的区别是什么?
    • 4.Category中有load方法吗?load方法是什么时候调用的?load方法继承吗?
    • 5.load、initialize方法的区别是什么?它们在category中的调用顺序是什么?以及出现继承时他们之间的调用过程?
      • 区别:
      • 在Category中的调用顺序:
      • 继承时它们之间的调用过程:
    • 6.Category能否添加成员变量?如果可以,如何给Category添加成员变量?

block

1.block的原理是怎样的?本质是什么?

在iOS中,Block是一种特殊的对象。封装了函数调用以及调用环境的OC对象。用于封装代码块。它可以作为参数传递给方法或函数,并且可以在稍后的时间点执行。

Block的本质是一个封装了一段代码以及其访问的变量的结构体。当定义一个Block时,它会捕获其所在作用域中的变量,并将这些变量的值复制到自己的内部结构中。这样,在Block执行时,即使变量已经超出了其作用域,仍然可以访问并使用这些变量的值。

block转成C++的源码:

//经过clang转换后的C++代码
struct __block_impl {
  void *isa;//指向所属类的指针
  int Flags;//标志性参数,暂时没用到所以默认为0
  int Reserved;//今后版本升级所需的区域大小。
  void *FuncPtr;//函数指针,指向实际执行的函数,也就是block中花括号里面的代码内容。
};

struct __main_block_impl_0 {
  struct __block_impl impl;//上面点1中的结构体的变量
  struct __main_block_desc_0* Desc;//上面点2中的结构体的指针 
  
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

static void __main_block_func_0(struct __main_block_impl_0 *__cself {
	printf("Block\n");
}

static struct __main_block_desc_0 {
  size_t reserved;  //今后版本升级所需区域的大小(一般填0)
  size_t Block_size;   //Block的大小
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};

int main(int argc, const char * argv[]) {
	void (*blk)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA));
	
	((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk);
    return 0;
}

关于block的具体细节可以看看之前的博客:【iOS】—— 浅看block源码
【iOS】—— 初识block

2.__block的作用是什么?有什么使用注意点?

在iOS中,__block是一个修饰符,用于在Block内部修改外部变量的值。它的作用是将外部变量在Block内部转为可修改的变量。

使用__block修符可以解决Block内部无法修改外部变的问题。默认情况下,Block内部能访问外部变量的,而不能修改它们。是,当你在外部量前面加上__block修饰符时,Block就可以修改这变量的值了。

以下是一些使用注意点:

  • __block修饰符只能于局部变量,不能用全局变量或静态变量。
  • 在Block部使用__block修的变量时,需要注意循环引用的问题如果Block被强引用并且同时引用了__block修饰的变,可能会导致环引用,造成内存漏。为了避免这种情况,可以在Block内部使用weakSelf来弱引用self,或者使用__weak饰符来修饰__block变量。
  • __block修饰的变量Block内部被修改,外部变量的值会被修改。这意味在Block执行完后,外部变量的值将保持被修改后的状态。
  • 在使用ARC(动引用计数)的情况下,__block饰符会自动处理内存管理。但是,在非ARC环境下,你需要手动处理__block变量的内存管理,确保Block执行完毕后释放它们。

3.block的属性修饰词为什么是copy?使用block有哪些使用注意?

  • block一旦没有进行copy操作,就不会在堆上。MRC 下 block 如果没有 copy 到堆上,值捕获不会对外部变量引用。 虽然 ARC 环境 strong 也可以修饰 Block,那是因为编译器会对 strong 修饰的 block 也会进行一次 copy 操作。
  • 因为Block的内存地址显示在栈区,栈区的特点就是创建的对象随时销毁,一旦销毁后续再次调用空对象就会造成程序崩溃。对Block进行copy操作之后,block存在堆区,所以在使用Block属性的时候Copy修饰。
  • 使用注意:循环引用问题

循环引用及强弱共舞可以看看之前的博客,上面有链接

4.block在修改NSMutableArray,需不需要添加__block?

不需要,给NSMutableArray添加元素时。__block修饰符主要用于在Block内部问和修改外部变量,以决Block内部对外部变量的捕获问题。而在修改NSMutableArray这样可变对象时,并不需要使用__block修饰符。因为NSMutableArray是一个指针类型的对象,当你在Block内部修改它,实际上是修改了指向该对象的指针,而是直接修改指针所指的对象本身。因此,无需使用__block修饰符来解决捕获问题。

5.关于block对不同种变量的捕获问题

先说结论:

  • 全局变量: 不捕获
  • 局部变量: 捕获值
  • 静态全局变量: 不捕获
  • 静态局部变量: 捕获指针
  • const修饰的局部常量:捕获值
  • const修饰的静态局部常量:捕获指针

局部变量:

    int dmy = 256;
    int val = 10;
    const char *fmt = "val = %d\n";
    void (^blk)(void) = ^{
        printf(fmt, val);
    };
    val = 2;
    fmt = "These values were changed. val = %d\n";
    blk();

输出结果:
在这里插入图片描述

全局变量

    void (^blk)(void) = ^{
        printf("%d\n", quanju);
    };
    quanju = 60;
    blk();

输出结果:
在这里插入图片描述

静态全局变量

    void (^blk)(void) = ^{
        printf("%d\n", jingquanju);
    };
    jingquanju = 60;
    blk();

在这里插入图片描述

静态局部变量

    int jingjubu = 10;
    void (^blk)(void) = ^{
        printf("%d\n", jingjubu);
    };
    jingjubu = 60;
    blk();

在这里插入图片描述

6.block捕获变量的原理是什么?

  • 在执行Block语法的时候,Block语法表达式所使用的自动变量的值是被保存进了Block的结构体实例中,也就是Block自身中。
  • 这里值得说明的一点是,如果Block外面还有很多自动变量,静态变量,等等,这些变量在Block里面并不会被使用到。那么这些变量并不会被Block捕获进来,也就是说并不会在构造函数里面传入它们的值。
  • Block捕获外部变量仅仅只捕获Block闭包里面会用到的值,其他用不到的值,它并不会去捕获。
    请添加图片描述

7.__block修饰符的作用

  • __block修饰对象类型的变量生成的结构体内部多了__Block_byref_id_object_copy__Block_byref_id_object_dispose两个函数,用来对对象类型的变量进行内存管理的操作。
  • __main_block_copy_0函数中会根据变量是强弱指针及有没有被__block修饰做出不同的处理,强指针在block内部产生强引用,弱指针在block内部产生弱引用。
  • 当修改__block修饰的变量时,是根据变量生成的结构体这里是__Block_byref_age_0找到其中__forwarding指针,__forwarding指针指向的是结构体自己因此可以找到变量进行修改。
  • 当block在栈中时,__Block_byref_age_0结构体内的__forwarding指针指向结构体自己。
  • 而当block被复制到堆中时,栈中的__Block_byref_age_0结构体也会被复制到堆中一份,而此时栈中的__Block_byref_age_0结构体中的__forwarding指针指向的就是堆中的__Block_byref_age_0结构体,堆中__Block_byref_age_0结构体内的__forwarding指针依然指向自己。

KVO

详解KVO的博客:【iOS】—— KVO再学习

1.iOS用什么方式实现对一个对象的KVO?(KVO的本质是什么?)

  • 利用RuntimeAPI动态生成一个子类,并且让instance对象的isa指向这个全新的子类
  • 当修改instance对象的属性时,会调用Foundation的_NSSetXXXValueAndNotify函数
  • 接着调用父类原来的setter方法;
  • 最后调用didChangeValueForKey,其内部会触发监听器(Oberser)的监听方法(observerValueForKeyPath:ofObject:change:context:);

总结

  • 主要用了isa-swizzling,修改了观察者的类信息,并且hooksetter方法,当setter方法调用时发送消息给所有观察者
  • 由上面源码可以看出对观察者、被观察者的引用都是Not Retain, 所以对象释放前一定要移除观察者。
  • 消息的发送主要由[self willChangeValueForKey: key], [self didChangeValueForKey: key]触发,并且必须成对出现,automaticallyNotifiesObserversForKey方法用来控制,是否要主要添加上述的两个方法,默认返回值为YES,如果返回NO则不会自动添加,也就是说setter的调用以及KVC修改都不会触发通知
  • + (NSSet<NSString *> *)keyPathsForValuesAffectingValueForKey:(NSString *)key
    此方法用来设置依赖关系,有时候需要某属性值随着同一对象的其他属性的改变而改变。可以通过事先将这样的依赖关系在类中注册,那么即便属性值间接地发生了改变,也会发送通知消息,被观察者类重写返回和key依赖的所有key集合
    内部实现也比较简单,将所有依赖关系存储在全局的dependentKeyTable中,然后hook了所有依赖的keysetter方法,当[self willChangeValueForKey: key], [self didChangeValueForKey: key]调用时会查找所有的依赖关系,然后发送消息
  • KVO内部多次用到了KVC
    • 重写 setValue:forKey
    • 使用valueForKey --- valueForKeyPath获取属性的值,尤其是在使用点语法的时候,只有valueForKeyPath可以获得深层次的属性值。
      所以KVO是基于KVC而实现的。

2.如何手动触发KVO?

  • 手动调用willChangeValueForKey:didChangeValueForKey:

3.直接修改成员变量会触发KVO么?

  • 不会触发KVO,KVO的本质是替换了setter方法的实现,所以只有通过set方法修改才会触发KVO。

KVC

详解KVC的博客:【iOS】—— KVC再学习

1.通过KVC修改属性会触发KVO么?

  • 会触发KVO。KVC在修改属性时,会调用willChangeValueForKey:didChangeValueForKey:方法;

2.KVC的赋值和取值的过程是怎样的?原理是什么?

赋值:KVC赋值(setValue:forKey:)

  • 首先会按照setKey_setKey的顺序查找方法,若找到方法,则直接调用方法并赋值;
  • 未找到方法,则调用+ (BOOL)accessInstanceVariablesDirectly;
  • accessInstanceVariablesDirectly方法返回YES,则按照_key_isKeykeyisKey的顺序查找成员变量,找到直接赋值,找不到则抛出异常;
  • accessInstanceVariablesDirectly方法返回NO,则直接抛出异常;
    在这里插入图片描述

取值:KVC取值(valueForKey:)

  • 首先会按照getKeykeyisKey_key的顺序查找方法,找到直接调用取值
  • 若未找到,则查看+ (BOOL)accessInstanceVariablesDirectly的返回值,若返回NO,则直接抛出异常;
  • 若返回的YES,则按照_key_isKeykeyisKey的顺序查找成员变量,找到则取值;
  • 找不到则抛出异常;
    在这里插入图片描述

Category

1.Category的使用场合是什么?

Category除了用来给类进行扩展外,还有一种比较高级的用法,就是用来拆分模块,将一个大的模块拆分成多个小的模块,方便进行维护和管理。什么意思呢?我就举一个很多开发人员都会存在的问题,就是AppDelegate这个类。这个类是刚创建项目时自动生成的,用来管理程序生命周期的。在刚创建项目时,这个类中是没有多少代码的,但是随着项目的进行,越来越多的代码会被放在这个类里面。比如说集成极光推送、友盟、百度地图、微信SDK等各种第三方框架时,这些第三方框架的初始化工作,甚至是相关的业务逻辑代码都会放在这个类里面,这就导致随着APP的功能越来越复杂,AppDelegate中的代码就会越来越多,有的甚至有几千行,看着就让人头皮发麻。

这时我们就可以利用Category来对AppDelegate进行拆分,首先我们就需要对AppDelegate中的代码进行划分,把同一种功能的代码抽取出来放在一个分类里面。比如说我可以新建一个极光推送的分类,然后把所有和极光推送有关的代码都抽出来放入这个分类,把所有和微信相关的代码抽出来放进微信的分类中,后面又有新的功要添加的话我只需要新建分类就好了。维护的时候要改什么功能的代码就直接找相应的分类就好了。

2.Category的实现原理

// 定义在objc-runtime-new.h文件中
struct category_t {
    const char *name; // 比如给Student添加分类,name就是Student的类名
    classref_t cls;
    struct method_list_t *instanceMethods; // 分类的实例方法列表
    struct method_list_t *classMethods; // 分类的类方法列表
    struct protocol_list_t *protocols; // 分类的协议列表
    struct property_list_t *instanceProperties; // 分类的实例属性列表
    struct property_list_t *_classProperties; // 分类的类属性列表
};
  • Category编译之后的底层结构是结构体struct category_t,里面存储着分类的对象方法、类方法、属性、协议信息。
  • 程序运行的时候,Runtime 会将Category的信息合并到类信息中(class类对象、mate-class元类对象),后合并的分类数据会插入到原来数据的前面;
  • 分类没有自己的class对象、和mate-class对象,因为一个类只有一个class对象、mate-class对象。

3.Category和Class Extension的区别是什么?

  • Class Extension是在编译的时候,它的数据都已经包含在类信息中了;
  • Category是在运行的时候,才将数据合并到类信息中。
  • 分类原则上只能增加方法,但是也可以通过关联属性增加属性
  • 拓展可以增加方法和属性,都是私有的。
  • 扩展只能在自身类中使用,而不是子类或者其他地方。
  • 类扩展是在编译阶段添加到类中,而分类是在运行时添加到类中

4.Category中有load方法吗?load方法是什么时候调用的?load方法继承吗?

  • +load方法。
  • +load方法会在Runtime加载类、分类的时候调用;
  • 每个类的+load方法只会调用一次;
  • 先调用类的+load方法,(按照编译顺序,先编译,先调用),调用子类的+load方法之前,会先调用父类的+load方法;
  • 再调用分类的+load方法,(按照编译顺序,先编译,先调用)。
  • 这里+load方法调用的顺序比较特别,没有先调用分类的+load方法,因为+load方法的调用机制不是objec_msgSend的方式,+load是直接找到方法地址进行调用的。
  • load方法能继承,不过一般不会手动调用load方法,都是系统自动调用。

5.load、initialize方法的区别是什么?它们在category中的调用顺序是什么?以及出现继承时他们之间的调用过程?

区别:

  • 调用时机
    load,当runtime加载类、分类时会调用。load方法总是在main函数之前调用,每个类、分类的load在运行时只调用一次
    initialize,在类第一次接收到消息时调用(先初始化父类,再初始化子类,每一个类只会被初始化一次)
  • 调用顺序
    load方法:先调用类的load,子类调用load方法之前会先调用父类的load,先编译的先调用;再调用分类的load方法,先编译的先调用
    initialize方法:先调用父类的initialize再调用当前类的initialize,如果子类没有实现initialize,则会调用父类的initialize;如果有分类,则调用最后编译的分类的initialize,就不调用本类的initialize了
  • 调用本质
    load,根据IMP地址直接调用(*load_method)(cls, SEL_load)
    initialize,通过objc_msgSend进行调用
  • 使用场景
    在load方法中实现方法交换(Method Swizzle)
    一般用于初始化全局变量或静态变量
  • 相同点
    两个方法会被自动调用,不需要手动调用他们
  • 区别
    load是通过直接函数地址调用,只会调用一次
    initialize是通过msgSend调用
    • 如果子类没有实现initialize,会调用父类的initialzie(所以父类的initialize会被调用很多次)
    • 分类如果实现了initialize,就会覆盖类本身的initailize

在Category中的调用顺序:

  • 如果有多个Category对同一个类实现了+load方法,它们的调用顺序是不确定的。编译器会将所有的+load方法放入一个全局的链表中,然后在运行时按照链的顺序依次调用。
  • 对于+initialize方法,如果一个类本身实现了+initialize方法,那么它会覆盖父类的+initialize方法。如果有多个Category对同一个类实现了+initialize方法,么只有最后一个被加载的Category的+initialize方法被调用。

继承时它们之间的调用过程:

  • 当一个类继承时,子类会继承父类的+load方法。父类的+load方法会在子的+load方法之前被调用。
  • 对于+initialize方法,子类如果没有实现自己的+initialize方法,继承父类的+initialize方法。父类的+initialize方法会在子类的+initialize方法之前被调用如果子类实现了自的+initialize方法,么父类的+initialize方法不被调用。

6.Category能否添加成员变量?如果可以,如何给Category添加成员变量?

不能直接给Category添加成员变量,但是可以间接实现Catecory有成员变量的效果。

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

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

相关文章

使用langchain与你自己的数据对话(一):文档加载与切割

LangChain是一个基于大语言模型&#xff08;如ChatGPT&#xff09;用于构建端到端语言模型应用的 Python 框架。它提供了一套工具、组件和接口&#xff0c;可简化创建由大型语言模型 (LLM) 和聊天模型提供支持的应用程序的过程。LangChain 可以轻松管理与语言模型的交互&#x…

简单理解TCP,UDP,HTTP

我们都知道TCP、UDP、HTTP内部有很复杂的过程&#xff0c;很多人没办法理解的那么深&#xff0c;只想知道这是个什么鬼。 1、TCP、UDP、HTTP 是什么? TCP/IP是个协议组&#xff0c;可分为三个层次&#xff1a;网络层、传输层和应用层。在网络层有IP协议、ICMP协议、ARP协议、…

50 Matplotlib Visualizations, Python实现,源码可复现

详情请参考博客: Top 50 matplotlib Visualizations 因编译更新问题&#xff0c;本文将稍作更改&#xff0c;以便能够顺利运行。 0 Introduction 新建项目文件夹为matplotlib_visualizations&#xff0c;以下所有的.py文件均默认在该位置。 0.2 Setup Setup.py文件内容如下&…

(双指针) 剑指 Offer 57 - II. 和为s的连续正数序列 ——【Leetcode每日一题】

❓ 剑指 Offer 57 - II. 和为s的连续正数序列 难度&#xff1a;简单 输入一个正整数 target &#xff0c;输出所有和为 target 的连续正整数序列&#xff08;至少含有两个数&#xff09;。 序列内的数字由小到大排列&#xff0c;不同序列按照首个数字从小到大排列。 示例 1…

zookeeper的应用

Zookeeper的配置文件解析: Zookeeper内部原理: 选举机制 半数机制:在集群环境中半数以上的机器存活,这个集群可用,所以在设计Zookeeper集群系统时&#xff0c;通常会选择 奇数台服务器来搭建Zookeeper的集群 虽然在配置文件中并没有指定Master和Slave。但是&#xff0c;Zookeep…

【安全狗】linux免费服务器防护软件安全狗详细安装教程

在费用有限的基础上&#xff0c;复杂密码云服务器基础防护常见端口替换安全软件&#xff0c;可以防护绝大多数攻击 第一步&#xff1a;下载服务器安全狗Linux版&#xff08;下文以64位版本为例&#xff09; 官方提供了两个下载方式&#xff0c;本文采用的是 方式2 wget安装 方…

09.计算机网络——套接字编程

文章目录 网络字节序socket编程socket 常见APIsockaddr结构 UDP编程创建socket绑定socketsendto发送数据recvform接收数据关闭socket TCP编程创建socket绑定socketlisten监听套接字accept服务端接收连接套接字connect客户端连接套接字send发送数据recv接收数据关闭socket 工具n…

算法训练营第四十六天||● 139.单词拆分 ● 关于多重背包,你该了解这些! ● 背包问题总结篇!

● 139.单词拆分 这道题和完全背包一样&#xff0c;求排列数相当于 字符串相当于背包&#xff0c;字串相当于物品 注意find方法的使用 find&#xff08;s.begin(),s.end(),"zichuan") 还有s.substr的使用s.substr(起始位置&#xff0c;截取长度&#xff09; clas…

Stable Diffusion服务环境搭建(远程服务版)

Stable Diffusion服务环境搭建&#xff08;远程服务版&#xff09; Stable Diffusion是什么 Stable diffusion是一个基于Latent Diffusion Models&#xff08;潜在扩散模型&#xff0c;LDMs&#xff09;的文图生成&#xff08;text-to-image&#xff09;模型。具体来说&#…

ES6基础知识一:说说var、let、const之间的区别

一、var 在ES5中&#xff0c;顶层对象的属性和全局变量是等价的&#xff0c;用var声明的变量既是全局变量&#xff0c;也是顶层变量 注意&#xff1a;顶层对象&#xff0c;在浏览器环境指的是window对象&#xff0c;在 Node 指的是global对象 var a 10; console.log(window.…

VUE3---->基础入门

目录 vue 基础入门 1、解读核心关键词&#xff1a;框架 2、vue 的版本 3、vue 的调试工具 vue 基础入门 vite 的基本使用 1. 创建 vite 的项目 2. 梳理项目的结构 3. vite 项目的运行流程 组件的基本使用 1. 组件的注册 2. 组件之间的样式冲突问题 3. 组件的 props …

穿透内网群晖NAS实现远程访问【无公网IP】

穿透内网群晖NAS实现远程访问【无公网IP】 现代科技日新月异&#xff0c;我们身边的电子设备也在不断更新&#xff0c;日积月累之下&#xff0c;被淘汰的电子设备越来越多&#xff0c;难道就让这些性能不算差的电子设备从此闲置么&#xff0c;这明显不符合我们物尽其用的原则&a…

记录安装stable diffusion webui时,出现的gfpgan安装卡住的问题

参考链接&#xff1a;(145条消息) 使用stable diffusion webui时&#xff0c;安装gfpgan失败的解决方案&#xff08;windows下的操作&#xff09;_新时代原始人的博客-CSDN博客

[書籍]思考的框架

圖片來源:博客來書店 《思考的框架》是一本極具啟發性和實用性的書籍&#xff0c;它以系統性和綜合性的方式引導讀者運用跨學科思維來解決問題和拓展思維視野。作者巧妙地整合了來自不同領域的思想家和學者的觀點&#xff0c;從心理學到經濟學&#xff0c;從哲學到科學等&#…

docker安装jdk

文章目录 1.安装镜像2.查看已安装的镜像4.运行容器5.进入JDK 容器6.查看JDK版本 1.安装镜像 找到所要安装的镜像版本&#xff0c;复制命令 输入命令&#xff0c;下载openjdk8镜像 命令作用docker pull openjdk:8拉取版本号为8的镜像 2.查看已安装的镜像 命令作用docker ima…

指针大厂笔试真题讲解(c语言篇)

大家好&#xff0c;我是c语言boom家宝&#xff0c;今天为大家带来的是c语言指针内容在大厂笔试中的真题讲解&#xff0c;希望能让初学者对指针有更深入的理解。 ps&#xff1a;如有侵权&#xff0c;请私信联系&#xff0c;立刻删除。 真题一&#xff1a; 答案&#xff1a;2 &…

SpringCloud分布式项目下feign的使用

新建一个feign的微服务&#xff08;后面统称为A&#xff09;&#xff0c;其他项目要使用利用maven导入该服务模块的依赖就行了 导入依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</…

【C++】STL——list的使用和介绍、list的构造函数及其使用、list迭代器及其使用

文章目录 1.list的介绍和使用2.list的构造函数&#xff08;1&#xff09;list (size_type n, const value_type& val value_type()) &#xff08;2&#xff09;list() 构造空的list&#xff08;3&#xff09;list (const list& x) 拷贝构造函数&#xff08;4&#xff…

Spring Boot创建与运行

Spring Boot创建与运行 ​ 经过之前 Spring 文章的铺垫&#xff0c;终于来到了基于 Spring &#xff0c;并且也是 Spring 最火的框架之一 Spring Boot &#xff0c;在企业或者个人项目中&#xff0c;基本都是使用 Spring Boot &#xff0c;所以 Spring Boot 在 Spring 的学习阶…

Spring Boot 源码学习之@EnableAutoConfiguration注解

EnableAutoConfiguration 注解 引言主要内容1. EnableAutoConfiguration 功能解析1.1 常见的自动配置示例1.2 源码介绍 2. Import 注解介绍3. AutoConfigurationPackage 注解介绍 总结 引言 在 Huazie 的上篇博文中&#xff0c;我们详细了解了关于 SpringBootApplication 注解…