面试题答案
一键面试类的初始化发生情况
- 首次发送消息:当向类发送第一个消息时,会触发类的初始化。例如,
[MyClass new]
或者[MyClass someClassMethod]
,此时如果该类尚未初始化,则会进行初始化。 - 子类初始化:当一个子类被初始化时,如果其父类还未初始化,那么父类会先被初始化。例如,定义了
SubClass
继承自SuperClass
,在初始化SubClass
时,若SuperClass
未初始化,则SuperClass
会先初始化。 - 访问类的非懒加载的静态变量:如果类中定义了非懒加载的静态变量(如
static int myStaticVar;
),并且在代码中访问了该变量,也会触发类的初始化。
类的初始化机制保证线程安全的方式
在Objective - C运行时,类的初始化是通过 +load
和 +initialize
方法来实现的,并且这两个方法有着不同的线程安全机制:
+load
方法:- 调用时机:在程序启动时,运行时系统会根据每个类在编译时的依赖关系,按照继承体系的顺序加载类和分类。每个类的
+load
方法会在其被加载时调用,并且只调用一次。先调用父类的+load
方法,然后再调用子类的+load
方法,分类的+load
方法会在类的+load
方法之后调用。 - 线程安全:运行时系统保证
+load
方法在程序启动过程中被调用,并且是在一个线程安全的环境下调用。这意味着多个线程不会同时调用同一个类的+load
方法,所以开发者不需要额外处理线程安全问题。
- 调用时机:在程序启动时,运行时系统会根据每个类在编译时的依赖关系,按照继承体系的顺序加载类和分类。每个类的
+initialize
方法:- 调用时机:
+initialize
方法在类或其子类接收到第一条消息之前被调用,并且只调用一次。如果子类没有实现+initialize
方法,当子类接收到消息时,会调用父类的+initialize
方法。 - 线程安全:运行时系统使用锁机制来确保
+initialize
方法的线程安全。在多线程环境下,当一个线程首次尝试调用+initialize
方法时,会获取锁。如果另一个线程已经在执行+initialize
方法,其他线程会等待锁的释放。这种机制保证了+initialize
方法只会被一个线程执行一次,避免了重复初始化的问题。同时,开发者在实现+initialize
方法时,也需要注意避免死锁等线程相关问题,因为如果在+initialize
方法中使用锁不当,可能会导致死锁。例如,不要在+initialize
方法中递归调用+initialize
方法或者在锁内进行可能导致死锁的操作。
- 调用时机: