zoukankan      html  css  js  c++  java
  • 对static静态成员的理解

    疑惑:

    数据成员可以分静态变量、非静态变量两种. 
     静态成员:静态类中的成员加入static修饰符,即是静态成员.可以直接使用类名+静态成员名访问此静态成员,因为静态成员存在于内存,非静态成员需要实例化才会分配内存,所以静态成员不能访问非静态的成员..因为静态成员存在于内存,所以非静态成员可以直接访问类中静态的成员.
     
     非成静态员:所有没有加Static的成员都是非静态成员,当类被实例化之后,可以通过实例化的类名进行访问..非静态成员的生存期决定于该类的生存期..而静态成员则不存在生存期的概念,因为静态成员始终驻留在内容中..
     
     一个类中也可以包含静态成员和非静态成员,类中也包括静态构造函数和非静态构造函数..
     
     对于winApp来说,静态成员对于程序员本身省了很多事,而且因为静态成员驻留内存,在方法与方法之间传递共享数据的时候,所以静态成员成了我的首选..但是不要因为方便,大量使用,尤其是在内存紧张或者
     用静态方法操作一些共享值的时候.或者要写多用户系统的时候,要慎之又慎.比如:
     static int id = 0;
     sql = "select * from table where id=" + id;
     
     如果这样写的话,在单机测试的时候没有问题,但是在多人同时对数据进行测试的时候,就会有问题了.假如,A用户访问他的id是20,则id的值在内存中为20,而此时B用户访问,他的id是30,则id在内存中的值是30..A用户的id值则被更改了..如果此时你将这个方法用非静态成员来写,则不会出现这样的情况..因为非静态成员是你声明的时候,实例化的时候才会分配内存..所以A用户访问的时候,App会因为A实例化而给A用户的请求分配内存..而B用户访问的时候也一样会因为B用户的访问而分配内存..所以两个用户访问的是不同的内存块..所以不会出现数据覆盖和错乱的现象...
     
    我想这样的情况应该能很好的说明静态变量和非静态成员的区别..
      
    相对于webApp而言,在winApp下使用static的时候要比webApp下考虑的因素要少的多,因为webApp本来就是一个多用户的系统,所以使用static的时候更应该小心..

    而我对static在webApp下的使用存在一个疑问,如果一个静态方法,例如:

    static string aa(string str){
     //经过一系列操作..
     return str;
    }

    或者返回一个DataSet的静态方法
    static DataSet aa(string str){
     //经过一系列操作..
     return DataSet;
    }

    这个时候,在访问量大的时候,程序出现了并发,会不会发生错乱??我以前的项目使用的公用函数类中使用了大量的静态方法,不过好在访问量不大,一直没有问题..在发这个文章之前,我查找了MSDN,CSDN,搜索了一些关于静态成员的文章,但是都没有一个明确的说明..虽然,自己在项目中也测试了这么长时间也没有问题..但是总觉得有这个可能发生..

    不知道大家是否在项目中碰到类似的疑惑呢??请有过这方面经验的朋友指教..


    答案:
    不说是否滥用,如果你出现冲突,说明你没有理解静态成员变量和静态方法的区别,静态方法本身只是一段代码,不管怎么调用他都不会出现问题。但静态成员变量就不行了,他被所有用户共享,如果一个用户改变了他,肯定会影响到别人,这就是常说的并发冲突问题,一般来说在修改共享成员变量时要lock! 


    关于静态方法和实例方法的一些误区。 

    一、    静态方法常驻内存,实例方法不是,所以静态方法效率高但占内存。
     
        事实上,方法都是一样的,在加载时机和占用内存上,静态方法和实例方法是一样的,在类型第一次被使用时加载。调用的速度基本上没有差别。
     
     
    二、    静态方法在堆上分配内存,实例方法在堆栈上。
     
        事实上所有的方法都不可能在堆或者堆栈上分配内存,方法作为代码是被加载到特殊的代码内存区域,这个内存区域是不可写的。
     
     
    三、    实例方法需要先创建实例才可以调用,比较麻烦,静态方法不用,比较简单。
        事实上如果一个方法与他所在类型的实例无关,那么它就应该是静态的,决不会有人把它写成实例方法。所以所有的实例方法都与实例有关,既然与实例有关,那么创建实例就是必然的步骤,没有麻烦简单一说。实际上上你可以把所有的实例方法都写成静态的,将实例作为参数传入即可。
        有些方法看似与所在的实例无关,如IComparer.Compare方法,但实际上每一个实现这个接口的类都只会负责自己类型实例的比较,这是C#1.x规范中没有泛型所带来的历史遗留问题。
        大部分静态方法是与类的实例有关的,如各种Parse方法,他做成静态的原因是他没有实例作为参数。其他的大多是出于语义或者其他目的的考虑。
  • 相关阅读:
    在有多个input的表单当中按回车按钮,如何不自动提交表单,而触发某个按钮的事件
    login.jsp
    json数据源
    translation.js
    cookie.js
    i18next.min.js
    struts2拦截器实现原理
    proxy-target-class="true" 与proxy-target-class="false"的区别(声明事务的时候)
    NavLink
    【转载】target='_blank' 安全漏洞示例
  • 原文地址:https://www.cnblogs.com/ZX-LMY/p/5819051.html
Copyright © 2011-2022 走看看