• 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模式的体现 

  • 相关阅读:
    错误:严重: Servlet.service() for servlet [appServlet] in context with path [] threw exception [Request processing failed; nested exception is org.mybatis.spring.MyBatisSystemException: nested exception is
    转 File "/usr/bin/yum", line 30 except KeyboardInterrupt, e:
    【转】C++和Java比较
    org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter 'xxxx' is not present
    Leetcode 423. Reconstruct Original Digits from English
    Maven中打包scope为system的Jar包
    Oracle常用函数和注意事项
    Vue中组件之间数据通信
    Vue中data数据响应问题
    JAVA爬虫对font-face字体反爬虫解密
  • 原文地址:https://www.cnblogs.com/whbk/p/6429105.html
Copyright © 2020-2023  润新知