static关键字的作用

static是一个修饰符,用于修饰成员(成员变量和成员函数):

1.当static修饰成员变量:

        static修饰成员变量是解决数据的共享问题,static修饰的数据是每个对象共享 的数据。如果所有对象中某一个属性的值是一样的,那么在内存中会造成大量的数据重复,所以我们可以把这个重复的数据拿出来,放在一个公共的地方,就用static修饰,如图:

                  

            这个公共的地方不在堆里也不在栈里,在方法区的静态区里,静态区中放一些静态变量和静态方法。而被静态修饰的变量和方法了一种调用方式:用类名调用。那么静态变量于成员变量的区别是什么呢?

首先明确一点,类类型变量与类变量不是一码事:类类型变量是由类定义的变量,类变量就是静态变量。

(1)    两个变量的生命周期不同。(也是静态的弊端,生命周期太长,但是也好过占用内存)

成员变量随着对象的创建而存在,随着对象的回收而被释放;

静态变量随着类的加载而存在,会随着类的消失而消失。虚拟机结束类才会消失,类本身是一个对象,在内存里面也是按照对象的形式存储的,只不过可以通过这个类对象创建很多对象来封装具体的数据,当类的数据过多的时候,垃圾回收机制可以对他进行回收,判定方式是如果类很长时间不用就把它清除,当再次使用再重新加载。

(2)   调用方式不同

    成员变量只能被对象调用;

    静态变量可以被对象调用,还可以被类名调用。(不管有没有对象,都建议用类名调用,因为这是静态的专属调用方式,可阅读性强,让人看了一目了然,知道这是静态变量)。

(3)    别名不同

成员变量也称为实例变量;

静态变量也称为类变量。

(4)  数据存储位置不同

成员变量数据存储在堆内存的对象中,所以也叫对象的特有数据;

静态变量数据存储在方法区(也叫共享区,数据区·····翻译的名字多着呢,还记得之前五个区不?)的静态区中,所以也叫对象的共享数据。(方法存在方法区,调用时进栈)

2.当static修饰成员函数:

       当static修饰成员函数,这个函数就成为了一个静态函数,静态函数可以直接访问静态成员,静态方法,但是如果要访问成员方法,只能通过对象访问。我们来解释一下这句话的意思。刚刚我们提到,静态变量和静态方法都是存放在静态区中的,会随着类的加载而加载,也就是说静态成员的出现比对象要早,所以如果静态函数要调用非静态方法,我们必须要在静态函数内部创建一个对象.,以保证这个对象是和静态方法一起出现的,这样才能使用这个对象访问非静态的方法和变量。

1.      静态方法只能访问静态成员(包含成员变量成员函数),非静态既可以访问静态又可以访问非静态。

2.      静态方法中不可以定义this过super关键字。(因为用类名调用静态方法时没有对象,所以this没有指向,所以写this是会报错的 )

三句话图解static在内存中的姿势:

                                                  

首先我们先来分析这段代码:

当我们执行StaticDemo2的字节码文件的时候,这个类被加载进内存,然后进行空间的开辟,不同种类数据存放在不一样的地方。方法区里有一个静态区,存放静态方法和数据,非静态区里存放非静态的方法和数据,它们都是被共享的。非静态区里面都有一个this所属,内容只能被对象调用;静态区里有一个所属是自己的类名,没有this,this是不能写在静态方法里的,所以此时,当我们调用这个StaticDemo2类的时候,内存的加载如下:

                                              

当运行到主函数的时候,主函数进栈:

     第一句话:使用到了Person类,此时找classPath路径下是否有Person.class文件,如果没有设置classPath,默认在当前路径下找,找到Person文件后加载Person类,加载完毕后,运行method()方法,method()方法进栈,语句执行完毕,运行默认的return语句,方法出栈。

                                                                   

第二句话:在主函数中定义一个Person类型的变量p,在堆中创建一个新对象,为对象分配地址,堆内存对对象进行数据初始化,然后传参数进行构造函数初始化,构造函数进栈,执行完毕弹栈。

 

                                                         

第三句话:p.show()在编译运行之前都要检查是否有show()方法,如果有show()方法,show()方法进栈,并且show()方法是非静态的方法,所以show()方法里也应该有默认的this引用,此时this的值是所属的函数的调用对象的值,在输出语句中可以通过类的所属找到country,通过this找到name和age。执行完毕后结束函数。

                                                                

什么时候使用静态?

静态只能修饰成员(成员变量,成员函数)

1. 静态变量;

不加静态是在对象里,加了静态是在方法区里;

不加静态是对象特有,加了静态对象共有。

当分析对象中所具备的成员变量的值都是相同的,这个成员就可以被静态修饰,但是如果有一个值不是相同的或者可以被改变,那就不可以用静态。

只要数据在对象中都是不同的,就是对象的特有数据,必须存储在对象中,是非静态的;

如果是相同的数据,对象不需要做修改,只需要使用即可,不需要存储在对象中。(如存在对象中也可以,但是会造成空间的浪费,但是也不可以都用静态,这样问题分析不好,生命周期过长)

2. 静态函数;

函数是对外提供的功能,但是函数是否用静态修饰就参考一点,这个函数是否访问到对象的特有数据。

简单点说,从源代码看,该功能是否需要访问非静态的成员变量,如果需要,该功能就是非静态的。如果不需要,就可以将该功能定义成静态的当然也可以定义成非静态,但是非静态需要被对象调用,而仅创建对象调用非静态的方法,没有访问特有数据,该对象的创建是没有意义的。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值