static静态与非静态

  以前对静态的了解只停留在语法、使用方式上面,今天看了《你必须了解的.NET》中的:动静之间—静态和非静态和园子里面关于static的一些文章,才对静态有了一个更加深入的了解。

一、静态简介

     很多情况下,实例特征主宰天下,类相当于一个特征模板,而对象就是这个模板的拷贝,并且独立于其他对象来操作这些特征。但是,在某些情况下,我们需要某些特征被所有的对象实体共有,因此有必要实现一种基于类的特征,而不是基于实例的特征机制,这就是静态,简单来说就是:一个类的实例共享同一个成员变量

二、静态的特征

     不需要new,直接通过"类名."的方式调用     

三、静态成员特征

     ① 静态字段、属性    

//类Consumer  
    public class Consumer
    {
        private double cost;
        public double Cost
        {
            get { return cost; }
            set { cost = value; }
        }

        private static double costAll;
        public static double CostAll
        {
            get { return costAll; }
            set { costAll = value; }
        }
        //计算消费总额方法
        public void AddCost()
        {
            costAll += cost;
        }
        //打印消费总额
        public void ShowCost()
        {
            Console.WriteLine(CostAll);
        }
    }
//在Main中调用
    static void Main(string[] args)
     {
            Consumer consumber1 = new Consumer();
            consumber1.Cost = 5.25;
            consumber1.AddCost();
            Consumer consumber2 = new Consumer();
            consumber2.Cost = 3.23;
            consumber2.AddCost();
            //结果都是8.48  因为输出的都是static值,共享数据的体现
            consumber1.ShowCost();
            consumber2.ShowCost();
     }

  总结:(1):不需要再各个类里面都重复同样的数据,从性能上来讲,静态成员避免了不必要的数据

              (2):体现了数据共享的机制,同时也避免了以附加操作来处理每个对象都共享的数据信息

              (3):静态成员不能被对象调用,只能以"类."的形式进行调用

     ② 静态方法与实例方法

//类StaticMethodDemo
public class StaticMethodDemo
    {
        public static string staticString = "static string";
        public string noStaticString = "no static string";
        //StaticMethod
        public static void StaticMethod()
        {
            //1、静态方法也可以重载
            //2、静态成员不能被标记为:virtual,override,abstract
            //不能直接调用noStaticString通过 实例.noStaticString,不能使用this关键字
            Console.WriteLine(staticString);
        }
        //noStaticMethod
        public void NoStaticMethod()
        {
            //可以使用this关键字,可以调用静态和非静态成员
            Console.WriteLine(this.noStaticString);
            Console.WriteLine(staticString);
            Console.WriteLine(noStaticString);
        }
    }
//派生自StaticMethodDemo的类StaticMethodChildrenDemo
public class StaticMethodChildrenDemo:StaticMethodDemo
    {
        //具体实现
    }
//Main
static void Main(string[] args)
        {
            StaticMethodDemo staticMethodDemo = new StaticMethodDemo();
            //只有对象才能调用实例方法,对象无法调用静态成员
            staticMethodDemo.NoStaticMethod();
            //使用类直接调用静态成员
            StaticMethodDemo.StaticMethod();
            Console.WriteLine(StaticMethodDemo.staticString);
            //派生类可以调父类中的静态方法,但是无法重写,因为静态方法无法使用virtual,override,abstract来修饰
            StaticMethodChildrenDemo.StaticMethod();
        }

总结异同点: (1):静态方法可以重载。静态方法使用类名引用,实例方法使用对象引用

                 (2):静态方法不能使用virtual,override,abstract来修饰

                    (3):静态方法内部不能使用this关键字,因为静态成员是类独有的,非静态方法可以

                       (4):静态方法内部,不能调用非静态成员,但是实例方法中可以调用静态和飞静态成员

                       (5):派生类可以调用父类中的静态方法,同样是"类名."的方式,对象无法调用静态成员

                       (6):在性能上,静态方法与实力方法的差别不大,都是在JIT(Just in time即时编译器)类时分配内存,两者的区别仅在于:实例方法需要当前对象指针指向该方法,而静态方法可以直接调用,在性能上差别很小。

     ③ 静态构造函数和非静态构造函数

 public class StaticDemo
    {
        public static string staticStr = "Hello";
        public  int noStaticnumber = 0;
        public string MyProperty { get; }
//只读的静态字段 public static string MyProperty2 { get; }
//静态只读字段
  public static readonly string str; //静态构造函数中不能初始化非静态字段 static StaticDemo() { staticStr = "静态构造方法"; //noStaticnumber = 10; } //能初始化静态字段和非静态方法,但是不能给静态只读字段赋值 public StaticDemo() { staticStr = "构造方法"; noStaticnumber = 1; //通过 MyProperty = "1"; //报错 MyProperty2 = "2"; } }

总结异同点:(1):静态构造函数,可以与无参的实例构造函数同存,但二者的执行时间不同,静态构造函数在运行库加载类的时候被执行,而实例构造函数是类实例化的时候执行,静态构造函数只执行了一次,但是一个类的实例构造函数执行的次数取决于创建对象的次数

                     (2):静态构造函数,只能对静态成员进行初始化,无法对非静态成员进行初始化。而非静态构造函数两者都可初始化,但是无法初始化只读的静态字段和静态只读字段

   图解构造函数的执行顺序

         

               *静态成员的内存分配、成员初始化和构造函数只被执行一次,在JIT编译的时候,下一次创建对象实例的时候,只会执行实例成员的初始化过程

四、总结静态与非静态之间的异同点

     (1)、静态类中只能包括静态成员,否则编译器会抛出错误。非静态类中都可以包含。

      (2)、静态类不能被实例化,非静态类可以被实例化。但是不管是静态类或是非静态类来说,调用静态成员和静态方法都必须使用类去调用

      (3)、System.Console就是一个典型的静态类

      (4)、如果一个类中只包含静态成员和静态方法,那么应该把这个类标记为static,并提供私有的构造函数,来避免实例创建,这其实是一种MonoState模式的体现 

原文地址:https://www.cnblogs.com/whbk/p/6429105.html