【Java】——static关键字

版权声明:希望各位能遵守各自内心的原则 https://blog.csdn.net/weixin_40918067/article/details/82154792

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

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

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

static修饰成员变量

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

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

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

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

                   

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

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

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

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

  • 1)、别名不同???——》成员变量也称为实例变量;静态变量也称为类变量。
  • 2)、两个变量的生命周期不同???——》也是静态的弊端,生命周期太长,但是也好过占用内存;
  •                                                               ——》成员变量随着对象的创建而存在,随着对象的回收而被释放;
  • 3)、静态变量随着类的加载而存在,会随着类的消失而消失???——》虚拟机结束了,类才会消失,并且类本身是一个对象,在内存里面也是按照对象的形式存储的,只不过可以通过这个类对象创建很多对象来封装具体的数据;
  • 4)、当类的数据过多的时候,垃圾回收机制可以对旧数据进行回收???——》当再次使用再重新加载,如果类很长时间不用就把它清除;
  • 5)、调用方式不同???——》成员变量只能被对象调用;                                 
  •                                               ——》静态变量可以被对象调用,还可以被类名调用;
  • 注意:不管有没有对象,都建议用类名调用???——》这是静态的专属调用方式,可阅读性强,让人看了一目了然,知道这是静态变量;
  • 6)、类的类型变量与类变量不是一码事???——》类的类型变量是由类定义的变量,类变量就是静态变量;
  • 7)、数据存储位置不同???——》成员变量数据存储在堆内存的对象中,所以也叫对象的特有数据;
  •                                                       ——》静态变量数据存储在方法区的静态区中,所以也叫对象的共享数据;

注意:

  1. 方法区???——》也叫共享区,数据区·····翻译的名字多着呢,还记得之前五个区不?
  2. 方法存在方法区,调用时进栈;

当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修饰;

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

猜你喜欢

转载自blog.csdn.net/weixin_40918067/article/details/82154792