讲解顺序

  • 背景

  • 静态字段

  • 静态函数

  • 静态方法

  • 疑问解答


  • 背景

    • static来源

    在编写类的时候,有时候需要类里面的某个成员具有唯一性,也就是,对所有的对象都保持只有一个的状态。比如创建个人信息,我们都是中国人,但总不能每个人都要保存一个中国人字段吧,用一个就够了

    • static作用

    MSDN说:使用 static 修饰符声明属于类型本身而不是属于特定对象的静态成员。也就是说,用static修改的对象是一个类的全部成员,不属于某个类特有的。比如,轿车有四个轮子,而不是某种轿车有四个轮子。

    • static特性

    1、访问不需要声明类对象。比如

    Console.Write();//Write()这就是一个静态方法,不需要new Consolo();

    2、 static对象具有唯一性,无论是否产生了对象或无论产生了多少对象的情况下,某些特定的数据在内存空间里只有一份。也就是说,你无论new多少类成员,静态变量只有一个,要变都变。


    静态字段

    所谓静态字段,也就是有static修改的字段啦(对,就是废话o(∩_∩)o )。

    • 作用

    无论创建多少对象,静态字段代表的数据在内存空间中只有一个。比如说系统时间,无论你安装了多少软件,想知道现在几点了,都只有一个参考值,如果你改变了这个时间,那么其他软件获取的时间也都改变了。(当然,只是举例,具体咋访问时间的,俺不管)。

    • 操作顺序

    静态字段是在类操作(实例化、调用静态方法等)的时候第一个被实例化的对象。第二个是静态构造函数,而且他俩都只能被调用一次。

    • 特性

    1. 因为静态成员本身就是为了全局唯一性而生的,当然静态成员在整个函数内部相当于了全局变量。
    2. 静态成员只能被初始化一次,就是在第一次对这个类进行操作的时候创建。其他对整个类进行操作的时候,因为静态成员已经有了,自然不会再创建。(就是给菜鸟写的废话,不然很多人会有疑问,比如我。)
    • 举例

    ·如上图,每次创建实例的时候,构造函数对两个字段进行+1,但是结果不一样,这就是static修饰的字段的唯一性


    静态构造函数

    • 作用

    静态构造函数一般用来初始化静态变量,不会初始化非静态变量;但是因为非静态构造函数也能操作静态变量,所以就比较少用静态构造函数了。

    • 操作顺序

    无论对类进行何种操作,静态构造函数总是除了静态字段以外第一个被操作的方法,比非静态参数、非静态构造函数都要提前。

    • 特性
    1. 只能操作静态成员,因为非静态成员需要实体引用。
    2. 整个生命周期只会运行一次,且不可被调用。
    3. 静态构造函数不能有修饰符,因为只有系统才能调用,有没有public都没用;它也不能有输入参数。
    4. 如果类里面含有Main方法,则先执行静态构造函数;

    • 举例
    class A
    {
    public static int X; static A()
    {
    X = B.Y + 1;
    }
    }
    class B
    {
    public static int Y = A.X +1;
    static B()
    {
    } static void Main(string[] args)
    {
    Console.WriteLine(string.Format("Y={0}, X={1}", B.Y, A.X));//Y=2, X=1;
    Console.ReadLine();
    }
    }

    这是网上一个很有名的static的例子,如果不看答案,能够算出来才是本事。

    1. 首先,Main()方法在B类里面,所以需要先调用B类。

    2. 进入B类,先对静态字段Y分配空间,并默认赋值为0;注意,在这里Y已经初始化好了。

    3. 因为Y=A.X+1;所以操作A类的静态字段,现在进入A类。

    4. 同样的,先对A类的X分配空间并赋值为0。然后X=B.Y+1,B.Y已经存在了,为0,所以X=B.Y+1执行完后,X = 1。

    5. 调用A的静态构造函数。

    6. 完成Y的赋值,Y=A.X + 1,Y=2。

    7. 调用B的静态构造函数。

    8. 这时才会调用Main()方法,因为A.X,B.Y都完成了初始化并赋值,所以直接写出答案。

    能够将完整的顺序描述出来,static一般的面试题都难不住你了(我的意思是我很牛掰)


    静态方法

    • 应用

    静态方法一般用于频繁调用又不经常修改的地方。比如工具库方法、不需要实例化的方法、与具体业务无关,执行比较频繁,用的地方多的方法等。当然,这个特性也是因为静态方法无法被继承,无法进行扩展有关。

    • 操作顺序

    静态方法会在静态字段、静态构造函数都操作后才能被调用。

    • 特性

    1. 静态方法调用时不需要实例化类。
    2. 静态方法只能引用静态方法、字段、属性。静态方法里不能有非静态变量。

    3. 静态方法一经调用,就不能销毁,除非整个应用程序域都结束了。所以静态函数不能太多,否则一直占有内存。

    4. 因为静态方法不能访问非静态变量,所以与非静态方法耦合度较低,有利于代码的修改。

    5. 静态方法的执行效率比非静态方法要高,但是因为其一直占用内存不能被销毁,所以不能频繁使用静态方法。


    疑问解答

  • 静态变量与非静态变量最大的区别是什么?

    最大的区别在于内存的位置。静态变量的内存是在程序开始执时变量就占用了内存,直到整个程序结束时变量才释放内存. 非静态变量是在程序运行到该步的时候分配内存,并在执行完后自动销毁。所以:静态变量的值只会初始化一次,后面每次访问,都是上次处理过的值。

  • 为什么静态变量不需要实例化就能访问。

    因为类在初始化的时候,就已经为静态变量分配好了内存空间,不需要实例化就能准确找到它们的位置;而非静态成员必须在实例化类对象以后,才能确定它们的内存位置;因此也有这样的说法,静态成员是属于类,而非静态成员属于类的对象

    为什么静态方法里面不能访问非静态变量,也不能创建非静态变量?

  • 因为非静态变量需要实例化才能确认其内存中的位置,才能调用,而静态函数是不需要实例化的,所以静态方法不能使用

  • 为什么方法内部不能声明静态变量?

    因为静态变量是类所有实例的共用变量,也就是在该类的范畴内是个全局变量。而如果在方法内部定义静态变量,则会导致定义的静态变量是一个局部变量,如此定义自然会出错。

  • 静态成员的生命周期

    静态成员的生命周期是整个应用程序域的生存周期.也就是从操作含有静态成员的类开始,一直到整个应用程序结束。


  • 以上信息都是我参考无数资料自己整理的,当然有可能出现一些错误,欢迎大婶们指正,我会努力修改好,让这篇文章作为一篇优秀的static参考资料。

    C# static 干货全解析的更多相关文章

    1. 【凯子哥带你学Framework】Activity界面显示全解析

      前几天凯子哥写的Framework层的解析文章<Activity启动过程全解析>,反响还不错,这说明“写让大家都能看懂的Framework解析文章”的思想是基本正确的. 我个人觉得,深入分 ...

    2. iOS Storyboard全解析

      来源:http://iaiai.iteye.com/blog/1493956 Storyboard)是一个能够节省你很多设计手机App界面时间的新特性,下面,为了简明的说明Storyboard的效果, ...

    3. 【转载】Fragment 全解析(1):那些年踩过的坑

      http://www.jianshu.com/p/d9143a92ad94 Fragment系列文章:1.Fragment全解析系列(一):那些年踩过的坑2.Fragment全解析系列(二):正确的使 ...

    4. Java JVM 内存泄漏--全解析和处理办法 [ 转载 ]

      Java JVM 内存泄露——全解析和处理办法 [转载]   @author 小筐子 @address http://www.jianshu.com/p/bf159a9c391a         JA ...

    5. Dagger2 使用全解析

      Dagger2 使用全解析 Dagger是一个注入工具,何为注入,我们要生产一批机器人,每个机器人都有一个控制器,我们可以在机器人内部 new 出一个控制器: class Robot { val co ...

    6. Java7/8 中的 HashMap 和 ConcurrentHashMap 全解析

      Java7/8 中的 HashMap 和 ConcurrentHashMap 全解析 今天发一篇”水文”,可能很多读者都会表示不理解,不过我想把它作为并发序列文章中不可缺少的一块来介绍.本来以为花不了 ...

    7. Gson全解析(中)-TypeAdapter的使用

      TypeAdapter介绍 前面的Gson全解析(上)中我们理解并分别运用了JsonSerializer和JsonDeserializer进行JSON和java实体类之间的相互转化.这里利用TypeA ...

    8. OC分类(类目/类别) 和 类扩展 - 全解析

      OC分类(类目/类别) 和 类扩展 - 全解析   具体见: oschina -> MyDemo -> 011.FoundationLog-OC分类剖析 http://blog.csdn. ...

    9. Android Activity启动流程源码全解析(1)

      前言 Activity是Android四大组件的老大,我们对它的生命周期方法调用顺序都烂熟于心了,可是这些生命周期方法到底是怎么调用的呢?在启动它的时候会用到startActivty这个方法,但是这个 ...

    随机推荐

    1. 模态运行EXE程序

      function ExecShowModal(APath: PChar; ACmdShow: Integer; ATimeout: Longword): Integer; var vStartupIn ...

    2. perl 定义post接口

      [root@wx03 mojo]# cat a1.pl use Digest::MD5; my $md5 = Digest::MD5->new; $md5->add(1234567); p ...

    3. bzoj3191

      其实这是一个约瑟夫问题的变种首先我们先处理这样一个问题已知n个人,编号0~n-1,每k人干掉一个,问最后留下来的是谁当n,k非常大的时候,模拟是不行的,这时候我们考虑重编号第1次退出的肯定是肯定是编号 ...

    4. Light OJ 1017 - Brush (III)

      题目大意:     在一个二维平面上有N个点,散落在这个平面上.现在要清理这些点.有一个刷子刷子的宽度是w. 刷子上连着一根绳子,刷子可以水平的移动(在X轴方向上).他可以把刷子放在任何一个地方然后开 ...

    5. 图论(网络流):UVa 1659 - Help Little Laura

      Laura Luo has just invented a game. Given a beautiful pencil sketch with n points, you're to coloriz ...

    6. DIV+CSS布局问题:一个宽度不确定的DIV里面放三个水平对齐的DIV,左右两个DIV宽度固定为150px,中间那个DIV充满剩余的宽度

      一个入门的DIV+CSS布局问题:一个宽度不确定的DIV里面放三个水平对齐的DIV,左右两个DIV宽度固定为150px,中间那个DIV充满剩余的宽度. 说明:代码非真实情况下使用,所以直接简单. 没耐 ...

    7. C数组的相关知识

      数组的定义:具有相同数据类型的集合.在内存中开辟连续的存贮空间,从上往下,依次存储 补充:内存是以字节位单位的存储空间,内存中的每一个字节都唯一对应一个编号.这个编号就是地址.只要是存在内存中的数据都 ...

    8. String Problem - HDU 3374 (kmp+最大最小表示)

      题目大意:有一个字符串长度为N的字符串,这个字符串可以扩展出N个字符串,并且按照顺序编号,比如串  ” SKYLONG “ SKYLONG 1 KYLONGS 2 YLONGSK 3 LONGSKY ...

    9. 414. Third Maximum Number

      这个题有点坑啊..主要是自己蠢,以为 Integer.MIN_VALUE -1 == -2147483649 public class Solution { public int thirdMax(i ...

    10. jEdit应用指南【基础篇】

      jEdit是Java编写,强大,易用的程序员文本编辑器 jEdit是一个成熟的,设计优秀的程序员文本编辑器,已经有了7年的开发历史.在功能和易用性方面压倒许多昂贵的开发工具时,jEdit在GNU公用许 ...