进一步理解静态方法与实例方法的区别和实际应用

进一步理解静态方法与实例方法的区别和实际应用

标签(空格分隔): CSharp

以前对静态方法与实例方法的理解,仅限于知道静态方法不需要实例化对象就可以被直接调用,且静态方法在内存中只存一份,是全局性的,而实例化方法则必须实例化对象才能被调用,且在内存中每实例化一次就存一份。平时对静态方法的使用也比较少,一般也只在写一些公共使用的工具类方法的时候才用到,大部分时候都是操作实例化方法比较多。最近对阅读了一些有关静态方法和实例方法方面的技术文章,对其区别和实际应用进行了进一步的理解。

1、网络上对静态方法和实例方法的一些认识

下面分别列出了各个软件攻城狮们对静态方法与实例方法的认识,这些主要来源于志良的技术博客

  • A君认为两者之间几乎没有区别,在不需要实例化的情况下,就使用静态方法,在需要考虑稳妥的情况下,则需要使用实例方法,这样才可调用其他实例方法和变量。
  • B君认为在写公共的方法,且是零散的方法的时候,一般使用静态方法。
  • C君认为静态方法使用的比较少,因为其在应用一启动就实例化了,比较占资源。但是其在配合单例模式使用的时候比较好用,此外,比较多的使用在数据连接上。
  • D君认为静态就是类的,实例就是对象的。此外,静态方法不需要依赖类当中的属性,能在这个方法中封闭的完成一个功能,而实例方法更多的会使用到类当中的属性。
  • E君认为两者最大的区别在于内存。静态方法在程序开始时生成内存,实例方法在程序运行中生成内存,所以静态方法可以直接调用,实例方法要先生成实例,通过实例调用方法,静态速度很快,但是多可会占内存。任何语言都是对内存和磁盘的操作,至于是否面向对象,只是软件层的问题,底层都是一样的,只是实现方法不同。静态内存是连续的,因为是在程序开始时就生成了,而实例申请的是离散的空间,所以没有静态方法快。而且静态内存是有限制的,太多了程序会启动不了。
  • F君认为静态方法与实例方法各有自己的用处。到底是定义成静态方法,还是定义成实例方法,还要看具体情况,比如方法本身与类型没有太大的关系,可以定义成静态方法。使用实例方法时,则需要先创建实例,才能调用实例方法,而静态方法则不需要。从性能上来说,静态方法效率要稍微高一些,但是它会常驻内存。一些情况下使用静态方法是有好处的,因为静态方法无论你有多少实例,内存中只要维护一份拷贝。
  • G君认为两者牵扯到的东西比较多,诸如设计模式等等。简单点说,静态方法用来执行无状态的一个完整操作,实例方法则相反,它通常是一个完整逻辑的一部分,并且需要维护一定的状态值。如果用内存和效率来区分使用静态方法和实例方法就回到过去结构化编程了。使用那种方法的根本出发点还是围绕面向对象来进行的。

2、对静态方法和实例方法的进一步理解

从上述可知,大家都觉得实例化方法使用更多且稳妥些,静态方法尽量少用。
对静态方法与实例方法新理解:
1、静态方法常驻内存,实例方法则不是,所以静态方法效率高但占内存?
事实上,他们都是一样的,在加载时机和占用内存上,静态方法和实例方法是一样的,在类型第一次被使用时加载。调用的速度基本上没有差别。
2、静态方法在堆上分配内存,实例方法在堆栈上?
事实上所有的方法都不可能在堆或者堆栈上分配内存,方法作为代码是被加载到特殊的代码内存区域,这个内存区域是不可写的。
方法占不占用更多内存,和它是不是static没什么关系。
因为字段是用来存储每个实例对象的信息的,所以字段会占有内存,并且因为每个实例对象的状态都不一致(至少不能认为它们是一致的),所以每个实例对象的所以字段都会在内存中有一分拷贝,也因为这样你才能用它们来区分你现在操作的是哪个对象。
但方法不一样,不论有多少个实例对象,它的方法的代码都是一样的,所以只要有一份代码就够了。因此无论是static还是non-static的方法,都只存在一份代码,也就是只占用一份内存空间。
同样的代码,为什么运行起来表现却不一样?这就依赖于方法所用的数据了。主要有两种数据来源,一种就是通过方法的参数传进来,另一种就是使用class的成员变量的值……
3、实例方法需要先创建实例才可以调用,比较麻烦,静态方法不用,比较简单?
事实上如果一个方法与他所在类的实例对象无关,那么它就应该是静态的,而不应该把它写成实例方法。所以所有的实例方法都与实例有关,既然与实例有关,那么创建实例就是必然的步骤,没有麻烦简单一说。
当然你完全可以把所有的实例方法都写成静态的,将实例作为参数传入即可,一般情况下可能不会出什么问题。
从面向对象的角度上来说,在抉择使用实例化方法或静态方法时,应该根据是否该方法和实例化对象具有逻辑上的相关性,如果是就应该使用实例化对象 反之使用静态方法。这只是从面向对象角度上来说的。
如果从线程安全、性能、兼容性上来看 也是选用实例化方法为宜。
4、为什么要把方法区分为:静态方法和实例化方法?
如果我们继续深入研究的话,就要脱离技术谈理论了。早期的结构化编程,几乎所有的方法都是“静态方法”,引入实例化方法概念是面向对象概念出现以后的事情了,区分静态方法和实例化方法不能单单从性能上去理解,创建c++,java,c#这样面向对象语言的大师引入实例化方法一定不是要解决什么性能、内存的问题,而是为了让开发更加模式化、面向对象化。这样说的话,静态方法和实例化方式的区分是为了解决模式的问题。
拿别人一个例子说事:
比如说“人”这个类,每个人都有姓名、年龄、性别、身高等,这些属性就应该是非静态的,因为每个人都的这些属性都不相同;但人在生物学上属于哪个门哪个纲哪个目等,这个属性是属于整个人类,所以就应该是静态的——它不依赖与某个特定的人,不会有某个人是“脊椎动物门哺乳动物纲灵长目”而某个人却是“偶蹄目”的。

2.2、静态方法与实例方法在内存中

代码例子:

class Program
{
    static void Main(string[] args)
    {
        Person p = new Person();
        Person p1 = new Person();
        Person p2 = new Person();
    }
}

class Person
{
    //静态成员变量
    private static int nAge;
    //实例成员变量
    private string strName;

    public static void Run()
    {
        Console.WriteLine("我会奔跑!");
    }

    public void Sing()
    {
        Console.WriteLine("我会唱歌");
    }
}

静态方法与实例方法在内存中:
此处输入图片的描述

posted @ 2016-03-31 10:46  CanonGhost  阅读(6438)  评论(0编辑  收藏  举报