static
static静态类,在某个类中只有一个,不会因实例化对象的不同而不同。static可以修饰类、字段、属性、方法等。如一个方法前加上static修饰后,如果要对其进行调用可以直接通过类名点出来,不用再对类进行实例化。
如:iphone6s(类),下面有很多个6s(new 的实例) ,每个6s都有自己的软件(成员变量),所有的6s有一样的芯片,属于6s(static 成员)。
使用时必须指出 所有者 例如 “6s1号.软件” ,对于芯片(static)而言,他是属于所有6s,而不是属于特定的某个实例 ,使用时 只能表示为 6s.芯片。
1. 静态类(其实就是封装完了划好格子的类)
- 仅包含静态成员。
- 本质是一个抽象的密封类,不能被实例化,不能继承。
- 不能包含实例构造函数。
- 如果一个类下面的所有成员都要被共享,那么可以把类定义为静态类。
2.类的 静态成员
-
通过static关键字修饰,是属于类,不属于对象
-
静态成员只被创建一次,所以静态成员只有一份。不同于实例成员,有多少个对象,就有多少份。
-
类加载的时候,所有的静态成员就会被创建在“静态存储区”里面,一旦创建直到程序退出,才会被回收。
-
成员需要被共享的时候,方法需要被反复调用的时候,就可以把这些成员定义为静态成员。
-
在静态方法中,不能直接调用实例成员,因为静态方法被调用的时候,对象还有可能不存在。
-
this/base 关键字在静态方法中不能使用,因为有可能对象还不存在
-
在实例方法中,可以调用静态成员,因为这个时候静态成员肯定存在。
-
可以创建这个类的对象,制定对象的成员在静态方法中操作。
-
静态方法和属性不能访问其包含类型中的非静态字段和事件,并且不能访问任何对象的实例成员。
-
静态方法只能被重载,而不能被重写,因为静态方法不属于类的实例成员。
-
虽然字段不能声明为 static const,但 const 字段的行为在本质上是静态的。这样的字段属于类,不属于类的实例。
用处:举个栗子🌰
private string[] namelist = new string[size];
static public int size = 10;
不会报错,但是删掉static
3.类的 静态方法
将类成员函数声明为public static,无需实例化即可调用该类成员函数
4.类的静态构造函数
- 静态构造函数可以用于静态类,也可用于非静态类;静态构造函数不可继承;
- 静态构造函数无访问修饰符、无参数,只有一个 static 标志;
- 静态构造函数不可被直接调用,当创建类实例或引用任何静态成员之前,静态构造函数被自动执行,并且只在类第一次创建时才会被调用一次。(在类实例化之后执行的就是实例构造函数)
原博客代码:
//类定义
class Static_Test
{
public static int static_Tag = 0; //Flag
public static int static_Count = 0; //记录静态构造方法的调用次数
public int notStatic_TAG = 0; //实例成员变量
public Static_Test() //普通实例构造方法
{
static_Tag = 1;
Console.WriteLine("实例构造方法被引用");
} //无参构造方法
static Static_Test() //静态构造方法
{
static_Tag = 2;
//notStatic_TAG = 5;静态方法不能访问实例成员变量
static_Count ++; //存储调用次数
Console.WriteLine("静态构造方法被引用");
}
public Static_Test(int tmpTag) //带参构造方法
{
static_Tag = 3;
//成员方法可以访问静态变量
//静态成员不能用this
Console.WriteLine("带参构造方法被引用");
}
~Static_Test() //析构函数 作用释放空间
{
Console.WriteLine("析构函数被调用");
}
}
//主函数
static void Main(string[] args)
{
Console.WriteLine(Static_Test.static_Tag);
/*输出为2,函数开始所有的静态成员被创建在静态存储区当中,static_Tag = 0
*随后函数开始调用类的成员变量,调用时类的!!静态构造方法!!被使用访问 static_Tag = 2
注意是:类名.静态成员
*/
Static_Test s_T = new Static_Test();
Console.WriteLine(Static_Test.static_Tag);
/*输出结果为1,类实例化时会调用类的实例化函数,因为是无参,所以 static_Tag = 1,
*因为静态构造函数只有在类第一次创建时才会被调用,所以输出结果为 static_Tag = 1
*/
s_T = new Static_Test(5);
Console.WriteLine(Static_Test.static_Tag);
/*输出结果为3,类实例化时会调用类的实例化函数,因为是有参,所以 static_Tag = 3,
*/
Console.WriteLine("静态构造方法调用次数为 {0} ", Static_Test.static_Count);
//输出结果为1 因为静态构造方法只能被创建一次
Console.ReadLine();
}
5.类的 静态方法
-
静态全局变量
定义:在全局变量前,加上关键字 static 该变量就被定义成为了一个静态全局变量。
特点:
A、该变量在全局数据区分配内存。
B、初始化:如果不显式初始化,那么将被隐式初始化为0。 -
静态局部变量
定义:在局部变量前加上static关键字时,就定义了静态局部变量。
特点:
A、该变量在全局数据区分配内存。
B、初始化:如果不显式初始化,那么将被隐式初始化为0。
C、它始终驻留在全局数据区,直到程序运行结束。但其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束。 -
静态数据成员
特点:
A、内存分配:在程序的全局数据区分配。
B、初始化和定义:(程序一开始运行就必须存在,且要分配空间)
不能在类声明中定义,不能在类的头文件中定义。
初始化的最佳位置在类的内部
C、特点 没有产生类的实例时,我们就可以操作它。
D、访问形式 类对象名.静态数据成员名
E、静态数据成员,主要用在类的所有实例都拥有的属性上。(打包就是静态类)比如,对于一个存款类,帐号相对于每个实例都是不同的,但每个实例的利息是相同的。所以,应该把利息设为存款类的静态数据成员。这有两个好处,第一,不管定义多少个存款类对象,利息数据成员都共享分配在全局区的内存,所以节省存贮空间。第二,一旦利息需要改变时,只要改变一次,则所有存款类对象的利息全改变过来了,因为它们实际上是共用一个东西。
-
静态成员函数
特点:A、静态成员函数与类相联系,不与类的对象相联系。B、静态成员函数不能访问非静态数据成员。原因:非静态数据成员属于特定的类实例。
作用:主要用于对静态数据成员的操作。
调用形式:A、类对象名.静态成员函数名()