⭐️小剧场⭐️
阿花是一所大学的老师,班级周末组织了春游,她千叮万嘱大家必须要带上一瓶水,但是她还是非常担心有同学没带水,于是她带了一瓶桶装水在车上,到了检查后发现大家还好都有带水。但是她发现某个男同学已经把水喝完了,他固执地想喝另外一个女同学的水,女同学非常拒绝,这时还好阿花赶快抱出了这桶桶装水,男同学好奇地问:“为什么我能喝这桶水,不能喝她的水啊?”阿花不紧不慢地说:“因为她的水是成员变量,这桶水是静态变量呀”。
🎨 1.什么是Static关键字?
Static是一个用来修饰成员变量或成员方法的关键字,经过Static的修饰后,它会变成静态变量和静态方法
🎨 2.Static关键字的性质和特点
🐷 1.用来修饰成员方法和成员变量和代码块
public class Demo { static int a =10;//静态成员变量 //静态方法 public static void method(){ System.out.println("静态方法"); } static { System.out.println("静态代码块"); } }
🌲 书写格式:静态变量 :static 数据类型 变量名 = 数值
静态方法:权限 static 返回值类型 方法名称()
静态代码块 :static{ 方法体 }
🐷 2.静态方法与静态变量全解析
首先我们要知道,被static修饰过的资源称之为静态资源,包括静态变量和静态代码块以及静态资源。其中调用静态变量和静态方法可以直接通过类名去访问。
public class Demo{ static int a =10; int b=10; public static void method(){ System.out.println("静态方法"); } public void method2(){ System.out.println("成员方法"); } public static void main(String[] args) { //调用成员变量和成员方法 Demo demo = new Demo(); demo.method2();//成员方法 System.out.println(demo.b);//10 //调用静态变量和静态方法 Demo.method();//静态方法 System.out.println(Demo.a);//10 } }
这里我们一定要发现:调用成员变量和方法时一定得有一个Demo类的实例对象demo,不然我们发现成员变量和方法都是无法访问和调用的。而我们发现静态变量和静态方法,居然可以通过类名Demo直接访问。这就能说明一个问题:成员变量和方法依赖于对象而生存,而静态变量则依赖于类生存。这就可以回归我们的小剧场了。
⭐️回归小剧场⭐️
阿花的这个班级就好比一个类,每一位同学都是属于这个类的对象,而每个同学的水壶都是属于自己的成员变量,是不可以给别的对象访问到的,要访问这个变量也必须经过对象。这个变量只属于这个对象,好比水壶只属于拥有它的同学。阿花带的大桶装水,它不属于任何一个同学,但它属于这个班级,也就是依赖于这个班级也就是这个类生存,每一位同学也就是每一个对象都是可以去访问它的,所以当我们需要访问它时,只需要在它前面加上类名即可,即使班里没有同学也就是没有对象,也不会影响我们的这个大水桶(静态变量)。当然无论班里有多少同学,始终也都只会有这一个大水桶,也就是无论有多少个对象,都不会影响静态变量。
🔔 静态方法:成员方法其实也类比与成员变量,它不需要依照某个类而存在,当我们想直接通过类名去调用某个方法时,我们就可以将它设为静态方法。因为不需要依赖对象,既然没有对象,那就更谈不上this关键字的。所以
🐤 在静态方法中是不能调用非静态的方法和变量,但是在非静态的方法却可以访问静态成员变量和方法(这就是为啥每次发现主函数调用某方法会报错,因为主函数是静态方法,而你调用的函数非静态)
🌰3.静态代码块
静态代码块的格式在前面已经写过了,那它既不是修饰一个变量,又不是修饰一个方法,而是修饰一段代码,它到底有什么性质呢?
阿花的班级去春游的很开心,这时他们需要一起坐车回去了,这时大家需要排队等车门打开然后挨个上车,那么请问门需要打开几次?大家肯定都明白,门只用打开一次,从第一个开始进去之前就打开就好。总不能每进一个人就关上门重新打开进下一个人吧(当然也不是不可以 👀 )这种只需要在最开始完成一次的操作,我们就可以把它放入到静态代码块中,它只会在最开始执行一次,后面就再也不会执行了。这时就有问题了,最开始到底是什么时候?答案是-------------类加载。
🌲 什么是类加载?
类加载这个东西,短时间内是无法讲清楚的,有兴趣的可以去搜索一下,在这里我只短暂地和提及。类加载顾名思义肯定是和类有关,我们知道我们写的代码都是交给jvm去处理的,我们经常会在代码中定义各种各样的类,什么学生类Studeng啊等等,jvm肯定是需要去认识它和处理它的,这种认识的过程就叫类加载,当然认识只需要一次(毕竟你认识一个异性也不需要多次认识吧 🙈 )
类加载只会执行一次,静态代码块会在类加载时执行,所以永远也只会执行一次。如果有多个静态代码块,则它们按照顺序执行。其实所有静态资源都在类加载时就初始化好了,也就是说包括静态变量和方法。
🌲静态代码块有什么好处 ?
你问我有什么好处?你说前面门一开一关上一个人上的快,还是开一次所有人上完的效率更快?当然只是开个玩笑,其实静态代码块同样类似前面的静态变量和方法的那个味道,它属于类而不属于实例对象,它可以优化我们的程序,提升效率(还不懂就再去看看上车的例子👿)
当然静态资源不会被虚拟机GC回收掉,这样内存负荷会很大,但是非static方法会在运行完毕后被回收,减轻内存压力(所以不要想着每次写个方法就加个static上去 👍 )
public class Demo{ static { System.out.println("我是类加载"); } public static void main(String[] args) { System.out.println("我不是类加载"); } }
🐋 这样就很容易看出来static代码块执行的时间很早(类加载时期)
🌺 3.静态变量VS普通成员变量
🍋 1.所属不同 -----静态变量属于类,也叫类变量。成员变量属于对象,所以也叫实例变量(对象变量)
🍋 2.内存存储位置不同-------静态变量存储在方法区,成员变量存储在堆内存
🍋 3.内存出现时间不同--------静态变量随着类的加载而加载,随着类的消失而消失。成员变量随着对象的创建而存在,随着对象的消失而消失
🍋 4.访问方式不同---------静态变量可以通过类名访问,也可以通过对象访问。成员变量只能通过对象访问。
🎃 3.Static总结大全
1.static关键字可以修饰成员变量和成员方法
2.static关键字的特点:
🌹 被类的所有对象所共享(判断是否使用static的关键):
1.static修饰成员变量的值,该成员变量的值,就不存储在对象中了,而是大度存储了一份,被所有对象共享(多想想那个大水桶 💦 )
2.当static修饰成员方法的时候,该方法被当前类的所有对象共享,当前类对象.方法(和普通成员方法从共享的角度,几乎没有太大区别)
🌹 语法:类名.静态变量 类名.静态方法(实参列表)
🌹 静态上下文中(静态方法体中),无法访问非静态的成员变量或方法,只能访问静态的成员和和方法
🌹static的使用场景:当我们希望某个成员变量的值,被该类所有对象共享时(再想想大水桶),可以使用static修饰。当我们需要定义一个工具方法给别人调用(其他类)时,此时可以将该方法定义为静态方法。