DotNet中静态成员、静态类、静态构造方法和实例构造方法的区别与联系
在面向对象的C#程序设计中,关于静态的概念一直是很多人搞不明白的。下面介绍这些带“静态”的名称。
1.静态成员:
定义:静态成员是用static关键字修饰的成员(包括字段属性和方法)
所属:静态成员是属于类的,只能通过类名.对象名的形式访问,而不能通过对象名访问
存储:静态成员是存储在内存空间的静态存储区中,而不是存储在栈或者堆中
生存周期:静态成员的生存周期是从类第一次被加载到整个程序运行结束才被释放,和垃圾回收器GC没有关系
何时使用:当这个类中的某些属性要被共享,某些方法要被反复调用,这个时候才将这些成员设置为静态,只需要加载一次
//类加载:什么是类加载,这个概念和java中的类加载时一样的。类的代码存放在代码段中,只要类被访问一次就会加载一次,我的理解是只要程序中出现了类名 类就被加载一次,类一旦被加载,那些静态成员立即被加载到静态存储区中。
2.实例成员
相比于静态成员。实例成员就是静态成员的反面,
1.实例成员没有static关键字修饰,是属于对象的,在对象创建的时候才被创建
2.实例成员只能通过对象名来访问,因为他属于对象,对象有多少分,他就有创建多少份
3.实例成员是存放在堆内存中的(成员变量存放在堆中,而方法的局部变量就定义在栈中)
4.实例成员的生命周期是从对象被创建(new)到对象失去引用,被垃圾回收器回收
3.静态类
定义:被static关键字修饰的类就是静态类
说明:
1.静态类中只能定义静态的成员,不能定义实例的成员。至于为什么:通过查看static的IL代码,他是一个抽象类和密封类,抽象类是不能被实例化的,他只是众多类的一个抽象,是堆类的共同点的归纳,实例化没有意义
2.静态类不能被继承,因为他是一个密封类(abstract),密封类是无法被继承的,但是静态的类可以继承别的类
3.静态类中的所有成员都只能通过类名.成员名访问
何时定义:当类中所有成员属性都要被共享,所有方法都要被反复调用,这个时候不如将类设置为静态类,类的一切都存储在静态存储区中,这样就能提高开发效率
实例类
相比于静态类,就有了实例类
定义:实例类就是没有static关键字修饰的类
说明:实例类就是我们一般见到的类
1.实例类中所有的实例成员是存储在堆中的,从对象被创建(new)到对象失去引用被垃圾回收器回收为止
2.实例类可以被继承也可以继承其他类,当然也可以实例出一个对象。这个自然不用说
3.实例类中可以定义静态成员 和静态构造方法,但是在静态类中不能定义实例成员和实例构造方法
介绍完静态类和实例类,静态成员和实例成员的区别,接着讲一下静态构造方法和实例构造方法
静态构造方法:
1.静态构造方法:就是被static关键字修饰的构造方法(构造方法名和类名相同)
2.说明:静态构造方法是一个“三无产品”:即:无参数 无返回值 无重载
只要是构造方法本来就没有返回值,而静态构造方法没有没有参数,没有参数自然就没有重载,静态构造方法是被系统自动调用 的,不需要手动调用,因此就不需要手动选择重载。
3.调用时机:静态构造方法和其他静态成员一样,都是在第一次类加载就被加载到静态存储区的。但是静态构造方被自动的调用时机就 是在该类的成员第一次被访问之前。
4.什么是成员第一次被访问:这个问题曾经困扰我多时,经过查找资料,反复试验现在终于可以确定下来,类的成员第一次被加载分为方法和静态属性的第一 次被访问。至于方法第一次访问,就是在创建对象,实例构造函数被调用。这叫成员第一次被调用,至于静态属性,不是说类加载的时候为这个成员开辟空 间的同时赋初始值叫静态成员的访问,类加载的时候为成员赋初始值不叫成员访问。成员访问时在其他地方通过类名.静态成员名 访问才叫访问。在第一次 访问实例构造方法和第一次访问静态属性之前,静态构造方法才能被调用!
5.其他:当然静态构造方法也属于静态成员,自然符合静态成员的一些特性,比如他也不属于对象,属于类,存储在静态存储区中,从类第一次被加载从程序 完全退出,一直存在
实例构造方法
1.实例构造方法:就是我们常见的构造方法
2.说明:实例构造方法在对象中是默认存在的,如果程序员没有手动定义实例构造方法,那么编译器会自动帮我们生产一个无参数的并且为空方法体的方法构造方法,当然方法名和类名一样,这点可以在通过反编译查看,如果程序员手动创建了一个构造方法,那么编译器就不再为我们创建默认的构造方法
3.实例构造方法的一些特性:实例构造方法是没有返回值的,甚至连void都不用写,一般的实例构造方法必须为public,最少也要protected和internal否则根本无法创建对象。
4.实例构造方法之间的调用:实例构造方法不能被普通的方法调用,更不能被静态方法调用(静态方法不能调用实例成员,因为当静态方法存在的时候,实例成员还不一定存在),但是实例构造方法可以互相调用,通过 :this()方式调用
class Person() { public string Name{set;get;} public int Age{set;get;} public bool Gender{set;get;};
//通过this关键字调用其他的构造方法重载 public Peson():this(int age) { cw("我是构造方法1"); } public Peson(int age) { cw("我是构造方法2" + age); } }