分享

static 静态方法 非静态方法 静态代码块

 一本正经地胡闹 2019-09-02

当类的字节码被加载到内存时,实例方法不会被分配入口地址,只有该类创建对象时,类中的实例方法才分配入口地址,所以实例方法只能通过对象调用。

而类方法是当类加载到内存中,就分配了相应的内存地址,所以类方法不仅可以通过对象调用,也可以用类名调用。

静态方法(Static Method)和非静态方法(Non-Static Method)的区别总结如下:
1、静态方法属于类所有,类实例化前即可使用;
2、非静态方法可以访问类中的任何成员,静态方法只能访问类中的静态成员因为静态方法在类实例化前就可以使用,而类中的静态变量在实例化之后才分配内存
4、static内部只能出现static变量和其他static方法。而且static方法中还不能使用this等关键字,因为它是属于整个类;
5、静态方法效率上要比实例化高,静态方法的缺点是不自动进行销毁,而实例化的则可以做销毁

静态方法在类装载的时候被装载到内存(Memory),不自动进行销毁,会一直存在于内存中,直到JVM关闭

非静态方法在实例化后才会分配内存,当实例对象被JVM 回收之后,也跟着消失,不会常驻内存。

6、静态方法和静态变量创建后始终使用同一块内存,而使用实例的方式会创建多个内存。
主要区别:静态方法在创建对象前就可以使用了,非静态方法必须通过new出来的对象调用。
如:

public class Per{
public static String getType(){
return "人类";
}
public String getName(){
return "张三";
}
}

上面这个类中的getType方法,在没有new对象前这就可以这样用:
String type=Per.getType();//type="人类";
而getName方法则不能这样使用,编译都不会通过,getName必须这样:
Per p=new Per();
String name=p.getName();//name="张三";
当然,getType方法也可能通过对象调用:
String type=p.getType();//type="人类";

转自 https://zhidao.baidu.com/question/1433773942389340379.html

静态方法何时使用

  • 如果某些操作不依赖具体实例,那它就是静态的,反之如果某些操作是依赖具体实例的(例如访问一个特定会员的名称),那它就应该是实例化的。

  • 静态方法不用new对象可以直接调用

  • 1.与类相关与对象无关 
    2.不需要对象的“轻”方法 
    3.工厂方法

  • 如果某个方法是用频率较高,或者方法本身通用性较强,无需初始化类成员变量,则可以使用静态方法,那样方便,速度也快.

  • 可以直接拿来就用的方法,就算是静态的.

  • 肯定不涉及具体对象,因为静态方法内,是无法直接使用任何非静态成员的。

  • (1)制作工具类 
    (2)可以当作"作局"对象或方法来使用

  • 静态方法和实例方法是一样的,在类型第一次被使用时加载。调用的速度基本上没有差别。

  • 静态方法不用创建实例就可调用,比较简单从面向对象的角度上来说,在抉择使用实例化方法或静态方法时,应该根据是否该方法和实例化对象具有逻辑上的相关性,如果是就应该使用实例化对象  反之使用静态方法

  • 不需要生成对象的 
    经常频繁使用的 
    工具类里的(如SqlHelper)

  • 适当地使用static方法本身并没有什么,当一个人从来不懂使用多态、接口设计时,很自然地会滥用static方法。

  • 个人理解在多个类中需要调用并且是与对象无关的方法可设为静态方法,方便调用。

  • 所有对象共有的方法

  • 再不关系到任何于特定对象相关的操作 
    比如学生的年龄就是学生的相关。 
    修改学生的年龄就不适合用静态方法。 
    一般来说,如果你的方法里没有用到this关键字, 
    那就适合用静态方法

  • 通常通用的类中一些常用的方法可以设计为静态类

  • 只要是没有用到类的状态信息,只从参数获取信息的都可以为静态的

  • 可以实现某些特殊的设计模式:如Singleton

  • 由于没有this指针,可以把某些系统API的回调函数以静态函数的形式封装到类的内部

  • 可以封装某些算法,比如数学函数,如ln,sin,tan等等,这些函数本就没必要属于任何一个对象,所以从类上调用感觉更好

  • 总之,从OOA/OOD的角度考虑,一切不需要实例化就可以有确定行为方式的函数都应该设计成静态的

  • 静态方法与非静态方法最明显的区别就是如果某个方法是公共静态的,那么可以直接通过类名.方法名的方法来调用,而公共实例方法则需要事先实例化对象,然后才能调用。

  这些各种说法,基本上都是正确的。

 欢迎关注公众号"Devin说",会不定期更新技术知识。

转自 https://www.cnblogs.com/devinzhang/archive/2012/04/27/2473570.html

静态代码块

静态代码块指 Java 类中的 static{...} 代码块,主要用于初始化类,为类的静态变量赋初始值。

  • jvm在加载类时会执行静态代码块(即,类名.静态变量,类名.静态方法,实例化(new一个对象),都会执行静态代码块)。

  • 如果类中包含多个静态代码块,jvm会按它们在类中出现的顺序依次执行它们,每个静态代码块只会被执行一次。

  • 与之对应的是非静态代码块{...}。每实例化一次,就会执行一次。

注意:变量指基本数据类型非对象,局部变量不能被静态修饰 

1、(静态)成员变量存放在data segment区(数据区),字符串常量也存放在该区 

2、非静态变量,new出来的对象存放在堆内存,所有局部变量和引用地址存放在栈内存 

3、方法(包括静态方法)存放在code segment(方法块),存放代码片段,且只存放一次


public class Cat {

    //private static int sid = 0;

    private int sid = 0;

    private String name; 

    int id;

    Cat(String name) {

        this.name = name;  

        id = sid++;

    }

    public void info(){

        System.out.println

               ("My name is "+name+" No."+id);

    }

    public static void main(String arg[]){

        //Cat.sid = 100;

        Cat mimi = new Cat("mimi");

        mimi.sid = 2000;

        Cat pipi = new Cat("pipi");

        mimi.info(); 

        pipi.info();

    }

}

静态方法和实例方法区别及使用场景

从实际项目开发说起,这里有开发项目的三种方式: 

开发项目中把BLL和DAL分开,在BLL调用DAL的代码。 

一、在DAL中使用静态方法,不创建实例直接调用(大概有很多人都使用这种方式开发 ) 

class DAL 

public static string GetUserName(…); 

在BLL中调用: 

DAL.GetUserName(); 

二、在DAL中使用实例方法,采用静态成员模式(或Singleton)通过实例来调用: 

class DAL 

public static readonly DAL dal = new DAL(); 

public string GetUserName(…); 

在BLL中调用: 

DAL.dal.GetUserName(); 

三、在DAL中使用实例方法,每次调用之前先创建DAL对象的实例: 

class DAL 

public string GetUserName(…); 

在BLL中调用: 

DAL dal = new DAL(); 

dal.GetUserName();

开发方式一:我以为在一些情况下(比如 调用多个数据库、GetUserName(…)内部处理操作部分)会出现线程安全的嫌疑。这种开发方式不用New出对象,所以很普遍。 

开发方式二:应该多是应用在cs模式下,DAL在整个项目只会有一个对象存在,如果出现在B/S 我想不能兼容多种问题情况。而且也有线程安全的问题。 

开发方式三:应该是普遍使用的,能够兼容各种问题,也不会有线程不安全的嫌疑出现。

特别说明一下:在MS的pet3.0以前的版本 都采用了方式二,而到pet3.0和以后的版本 都采用了方式三,而且特别在开发说明文档中明确的解释了一下。我想应该是从兼容性上考虑的,从性能上方式二并不比方式三真正的高多少。

我特意以“你怎么理解并使用静态方法和实例化方法的?”这样的问题询问了多位程序员,他们开发的语言也不尽相同(c 、c++、java、c#) 

以下是他们的回答:

海龙说: 

公用的方法,而且是一些零散的 一般用静态方法 

张伟说: 

几乎没有区别,如果不需要实例化,就用静态方法;如果为了稳妥,就用实例方法,这样才可调用其他实例方法和变量 。 

萧远山说: 

静态方法比较少用,因为他在一启动就实例化了,比较占资源,当然,,配合单例模式还是比较好用的 

比较多的用在数据连接上,我避免使用的原则就是减少资源消耗。 

张新波说: 

静态方法意味着我在调用前不需要进行对其所属的类进行new操作,我主要会在工具类里面用到静态方法。

向详说: 

静态就是类的,实例就是对象的。 

静态方法和实例方法的区别之处还有一个地方:静态方法不需要依赖类当中的属性,能在这个方法中封闭的完成一个功能。实例方法更多的会使用到类当中的属性。 

winson_张林说: 

最大的区别在于内存。 

静态方法在程序开始时生成内存,实例方法在程序运行中生成内存, 

所以静态方法可以直接调用,实例方法要先成生实例,通过实例调用方法,静态速度很快,但是多了会占内存。 

任何语言都是对内存和磁盘的操作,至于是否面向对象,只是软件层的问题,底层都是一样的,只是实现方法不同。 

静态内存是连续的,因为是在程序开始时就生成了,而实例申请的是离散的空间,所以当然没有静态方法快, 

而且静态内存是有限制的,太多了程序会启动不了。 

showlover说: 

静态方法与实例方法各有自己的用处… 

是定义成静态方法,还是定义成实例方法,还要看具体情况,比如方法本身与类型没有太大的关系,可以定义成静态方法.. 

用实例方法,当然需要你先创建实例,才能调用实例方法,而静态方法则不需要.. 

从性能上说,静态方法效率要稍微高一些,但是它会常驻内存… 

一些情况下使用静态方法是有好处的,因为对于静态方法无论你有多少个实例, 

内存中要维护的一份拷贝。同时,某些方法,确实使用静态是比较恰当的.. 

Q.yuhen说: 

这个问题牵扯到的东西比较多,诸如设计模式等等。简单点说,静态方法用来执行无状态的一个完整操作,实例方法则相反,它通常是一个完整逻辑的一部分,并且需要维护一定的状态值。 

如果用内存和效率来区分使用Static Method、Instance Method 就回到过去结构化编程了。使用那种方法的根本出发点还是围绕面向对象来进行的。

陈亮说: 

静态方法和全局函数差不多的,实例方法是一个类里面的方法。

总结:大家对这个问题都有一个共识:那就是实例化方法更多被使用和稳妥,静态方法少使用。

有时候我们对静态方法和实例化方法会有一些误解。 

1、大家都以为“ 静态方法常驻内存,实例方法不是,所以静态方法效率高但占内存。” 

事实上,他们都是一样的,在加载时机和占用内存上,静态方法和实例方法是一样的,在类型第一次被使用时加载。调用的速度基本上没有差别。 

2、大家都以为“ 静态方法在堆上分配内存,实例方法在堆栈上” 

事实上所有的方法都不可能在堆或者堆栈上分配内存,方法作为代码是被加载到特殊的代码内存区域,这个内存区域是不可写的。 

方法占不占用更多内存,和它是不是static没什么关系。 

因为字段是用来存储每个实例对象的信息的,所以字段会占有内存,并且因为每个实例对象的状态都不一致(至少不能认为它们是一致的),所以每个实例对象的所有字段都会在内存中有一分拷贝,也因为这样你才能用它们来区分你现在操作的是哪个对象。 

但方法不一样,不论有多少个实例对象,它的方法的代码都是一样的,所以只要有一份代码就够了。因此无论是static还是non-static的方法,都只存在一份代码,也就是只占用一份内存空间。 

同样的代码,为什么运行起来表现却不一样?这就依赖于方法所用的数据了。主要有两种数据来源,一种就是通过方法的参数传进来,另一种就是使用class的成员变量的值…… 

3、大家都以为“实例方法需要先创建实例才可以调用,比较麻烦,静态方法不用,比较简单” 

事实上如果一个方法与他所在类的实例对象无关,那么它就应该是静态的,而不应该把它写成实例方法。所以所有的实例方法都与实例有关,既然与实例有关,那么创建实例就是必然的步骤,没有麻烦简单一说。 

当然你完全可以把所有的实例方法都写成静态的,将实例作为参数传入即可,一般情况下可能不会出什么问题。 

从面向对象的角度上来说,在抉择使用实例化方法或静态方法时,应该根据是否该方法和实例化对象具有逻辑上的相关性,如果是就应该使用实例化对象 反之使用静态方法。这只是从面向对象角度上来说的。 

如果从线程安全、性能、兼容性上来看 也是选用实例化方法为宜。 

我们为什么要把方法区分为:静态方法和实例化方法 ? 

如果我们继续深入研究的话,就要脱离技术谈理论了。早期的结构化编程,几乎所有的方法都是“静态方法”,引入实例化方法概念是面向对象概念出现以后的事情了,区分静态方法和实例化方法不能单单从性能上去理解,创建c++,java,c#这样面向对象语言的大师引入实例化方法一定不是要解决什么性能、内存的问题,而是为了让开发更加模式化、面向对象化。这样说的话,静态方法和实例化方式的区分是为了解决模式的问题。 

拿别人一个例子说事: 

比如说“人”这个类,每个人都有姓名、年龄、性别、身高等,这些属性就应该是非静态的,因为每个人都的这些属性都不相同;但人在生物学上属于哪个门哪个纲哪个目等,这个属性是属于整个人类,所以就应该是静态的——它不依赖与某个特定的人,不会有某个人是“脊椎动物门哺乳动物纲灵长目”而某个人却是“偶蹄目”的。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多