静态方法、类方法、实例方法
static 修饰局部变量:延长布局变量的生命周期
static 修饰全局变量:当前变量只能在当前文件中使用
static 修饰函数: 函数只能在当前文件中使用
静态:与程序的生命周期相同的数据结构,从程序启动时就存在,当程序停止时才被销毁。
静态变量:分为局部静态变量和全局静态变量两种,必须使用 “static” 关键字修饰。
局部静态变量: 一般定义在方法或者函数内部,使用static关键字修饰; 不会随着方法或者函数调用完成而销毁,它的生命周期与程序的生命周期一样。 局部静态变量是会被初始化一次。 void haha(){ static int a = 10; // 只有在第一次调用haha函数时,才会执行当前这句代码,之后无论调用几次haha函数,都不会执行当前代码。 NSLog(@"%i", a); } // 当haha函数调用完成后,不会被销毁。 全局静态变量: 一般定义在方法或者函数的外部,不被任何函数或者方法包裹,使用static关键字修饰。 全局静态变量的作用域为当前文件,只能被当前文件中的方法或者函数使用,其它文件的方法不能使用。 ---------------------Person.h----------------------------------- static int a; extern int b; void haha(void); @interface Person : NSObject @property(nonatomic, copy) NSString *name; @end ---------------------Person.m------------------------------------- #import "Person.h" static int a = 10; // 在Person.m文件中定义,只能在Person.m文件中使用,即使在h文件中声明,外部文件也不能访问。 extern int b = 20; // 定义为全局变量,可以在任何文件中使用。 void haha() { NSLog(@"haha"); NSLog(@"%i",a); } @implementation Person @end --------------------main.m--------------------------------------- int main(int argc, const char * argv[]) { NSLog(@"a=%i", a); // a=0 NSLog(@"b=%i", b); // b=20 }
静态方法和动态方法
在OC中没有静态方法,即在OC中不能使用 “static” 修饰方法。 在其它语言中使用static修饰的方法,为类方法。因此可以变相的称OC的静态方法为类方法,动态方法为实例方法。
静态函数和动态函数
使用 “static” 关键字修饰的函数为静态函数。 静态函数的特点:只能在定义它的文件中调用,其它文件无法使用,即使在h文件中声明也不行。 动态函数可以在任何文件中使用,只要在h文件中声明。 ------------------Person.h---------------------------------- #import <Foundation/Foundation.h> static void haha(void); void hehe(void); @interface Person : NSObject @property(nonatomic, copy) NSString *name; @end ------------------Person.m---------------------------------- #import "Person.h" @implementation Person void haha() { NSLog(@"haha"); } void hehe() { NSLog(@"hehe"); } @end ------------------main.m---------------------------------- int main(int argc, const char * argv[]) { hehe(); // 可以调用。 haha(); // 程序编译出错。 }
在java中我们已经知道类体中的方法分为实例方法和类方法两种,用static修饰的是类方法。二者有什么区别呢?当一个类创建了一个对象后,这个对象就可以调用该类的方法。
当类的字节码文件被加载到内存时,类的实例方法不会被分配入口地址,当该类创建对象后,类中的实例方法才分配入口地址,从而实例方法可以被类创建的任何对象调用执行。需要注意的是,当我们创建第一个对象时,类中的实例方法就分配了入口地址,当再创建对象时,不再分配入口地址,也就是说,方法的入口地址被所有的对象共享,当所有的对象都不存在时,方法的入口地址才被取消。 对于类中的类方法,在该类被加载到内存时,就分配了相应的入口地址。从而类方法不仅可以被类创建的任何对象调用执行,也可以直接通过类名调用。类方法的入口地址直到程序退出才被取消。 类方法在类的字节码加载到内存时就分配了入口地址,因此,Java语言允许通过类名直接调用类方法,而实例方法不能通过类名调用。在讲述类的时候我们强调过,在Java语言中,类中的类方法不可以操作实例变量,也不可以调用实例方法,这是因为在类创建对象之前,实例成员变量还没有分配内存,而且实例方法也没有入口地址。
其次,静态方法中只能调用静态成员或者方法,不能调用非静态方法或者非静态成员,而非静态方法既可以调用静态成员或者方法又可以调用其他的非静态成员或者方法。 class A { int x,y; static float f(int a){} float g(int x1,int x2){} } class B { public static void main(String args[]) { A a1=new A(); A.f(2,3); //合法。 a1.f(2,4); //合法。 a1.g(2,5); //合法。 A.g(3,2); //非法。 } }
总结:
- 静态方法和动态方法的加载时机不同。
- 静态方法内部只能调用静态方法或者静态成员,不能调用非静态方法或者非静态成员。
- 静态方法只能通过实例化对象才能调用非静态方法或者非静态成员。
- 非静态方法既可以调用非静态方法和非静态成员,又可以调用静态方法或者静态成员。