首页技术文章正文

Java——static关键字

更新时间:2018-09-12 来源:黑马程序员JavaEE培训学院 浏览量:

【Java】——static关键字

 

static是什么???——》一个修饰符

那static作用于那???——》用于修饰成员

什么是成员???——》成员变量和成员函数

 

static修饰成员变量

static为什么修饰成员变量???——》解决数据的共享问题???——》static修饰的数据可以被每个对象共享的数据

为什么需要被每个对象共享某个数据???——》如果所有对象中某一个属性的值是一样的,那么在内存中会造成大量的数据重复;

 

那怎么实现static的作用???——》

 

被修饰后的成员变量的存储如图所示:

                   

被static修饰后的成员变量的存储在哪里???——》即不在堆里也不在栈里,而是在方法区的静态区里

静态区???——》放一些静态变量和静态方法。

存放好了,那该如何调用这种数据(或方法)?——》类名调用

 

既然知道了static是什么和如何运用等;那么我们也该了解静态变量和成员变量有什么区别???——》

·1)、别名不同???——》成员变量也称为实例变量;静态变量也称为类变量。

·2)、两个变量的生命周期不同???——》也是静态的弊端,生命周期太长,但是也好过占用内存;——》成员变量随着对象的创建而存在,随着对象的回收而被释放;

·3)、静态变量随着类的加载而存在,会随着类的消失而消失???——》虚拟机结束了,类才会消失,并且类本身是一个对象,在内存里面也是按照对象的形式存储的,只不过可以通过这个类对象创建很多对象来封装具体的数据;

·4)、当类的数据过多的时候,垃圾回收机制可以对旧数据进行回收???——》当再次使用再重新加载,如果类很长时间不用就把它清除;

·5)、调用方式不同???——》成员变量只能被对象调用;——》静态变量可以被对象调用,还可以被类名调用;

·注意:不管有没有对象,都建议用类名调用???——》这是静态的专属调用方式,可阅读性强,让人看了一目了然,知道这是静态变量;

·6)、类的类型变量与类变量不是一码事???——》类的类型变量是由类定义的变量,类变量就是静态变量;

·7)、数据存储位置不同???——》成员变量数据存储在堆内存的对象中,所以也叫对象的特有数据;——》静态变量数据存储在方法区的静态区中,所以也叫对象的共享数据;

 

注意:

方法区???——》也叫共享区,数据区·····翻译的名字多着呢,还记得之前五个区不?

方法存在方法区,调用时进栈;

 

当static修饰成员函数

为什么static要修饰成员函数使之成为一个静态函数???——》这是因为static有其作用之处;

静态函数作用于哪里???——》可以直接访问静态成员,静态方法;但是如果要访问成员方法,只能通过对象访问;

为什么静态成员的出现比对象要早???——》静态变量和静态方法都是存放在静态区中的,会随着类的加载而加载

如何使静态函数调用非静态方法(或静态变量)???——》必须要在静态函数内部创建一个对象???——》以确保对象是和静态方法是一起出现的;???——》对象才调用非静态的方法和变量;

 

使用static修饰成员函数该注意以下几点:

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

2.静态方法中不可以定义this(写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。执行完毕后结束函数                                        不加静态是在对象里,加了静态是在方法区里;

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

对象的特有数据,必须存储在对象中???——》数据在对象中都是不同,不能使用static修饰;

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

 

作者:黑马程序员JavaEE培训学院

首发:http://java.itheima.com/


分享到:
在线咨询 我要报名
和我们在线交谈!