static症结字的寄义及运用场景
static是Java50个症结字之一。static症结字能够用来润饰代码块示意静态代码块,润饰成员变量示意全局静态成员变量,润饰要领示意静态要领。(注重:不能润饰一般类,除了内部类,这是为何?)
class A { static { System.out.println("A : 静态代码块"); } static int i ; // 静态变量 static void method() { System.out.println("A: 静态要领"); } }
简而言之,被static症结字润饰的内容都是静态的。
静态是相对于动态的,动态是指Java递次在JVM上运转时,JVM会依据递次的须要动态建立对象并存储对象(分派内存),对象任务完毕后,对象会被垃圾接纳器烧毁,即内存接纳由JVM一致管理并分派给其他新建立的对象;静态是指Java递次还没有运转时,JVM就会为加载的类分派空间存储被static症结字润饰的内容;如静态成员变量,Java类加载到JVM中,JVM会把类以及类的静态成员变量存储在要领区,我们晓得要领区是线程同享且很少发作GC的地区,所以被static症结字润饰的内容都是全局同享的,且只会为其分派一次存储空间。
所以当类的某些内容不属于对象,而由对象同享即属于类的时刻,就可以够斟酌是不是用static症结字举行润饰。
static症结字的的作用
1 润饰代码块
类顶用static症结字润饰的代码块称为静态代码,反之没有用static症结字润饰的代码块称为实例代码块。
实例代码块会跟着对象的建立而实行,即每一个对象都邑有自身的实例代码块,表现出来就是实例代码块的运转效果会影响当前对象的内容,并跟着对象的烧毁而消逝(内存接纳);而静态代码块是当Java类加载到JVM内存中而实行的代码块,由于类的加载在JVM运转时期只会发作一次,所以静态代码块也只会实行一次。
由于静态代码块的重要作用是用来举行一些庞杂的初始化事情,所以静态代码块追随类存储在要领区的表现情势是静态代码块实行的效果存储在要领区,即初始化量存储在要领区并被线程同享。
2 润饰成员变量
类顶用static症结字润饰的成员变量称为静态成员变量,由于static不能润饰局部变量(为何?),因而静态成员变量也能称为静态变量。静态变量跟代码块相似,在类加载到JVM内存中,JVM会把静态变量放入要领区并分派内存,也由线程同享。接见情势是:类名.静态成员名。
public class StaticTest { public static void main(String[] args) { System.out.println(D.i); System.out.println(new D().i); } } class D { static { i = 2; System.out.println("D : 静态代码块1"); } static int i; }
静态变量存储在类的信息中,且能够在线程间同享,那末它固然也属于该类的每一个对象,因而能够经由过程对象接见静态变量,但编译器并不支撑这么做,且会给出正告。
注重:
一个类的静态变量和该类的静态代码块的加载递次。类会优先加载静态变量,然后加载静态代码块,但有多个静态变量和多个代码块时,会根据编写的递次举行加载。
class D { static { i = 2; System.out.println("D : 静态代码块1"); } static { i = 6; System.out.println("D : 静态代码块2"); } static int i; }
能够想一下运转的效果。
静态变量能够不必显式的初始化,JVM会默认给其响应的默认值。如基础数据范例的byte为0,short为0,char为\u0000,int为0,long为0L,float为0.0f,double为0.0d,boolean为false,援用范例一致为null。
静态变量既然是JVM内存中同享的且能够转变,那末对它的接见会引起线程安全问题(线程A改写的同时,线程B猎取它的值,那末猎取的是修正前的值照样修正后的值呢?),所以运用静态变量的同时要斟酌多线程状况。如果能确保静态变量不可变,那末能够用final症结字一同运用防止线程安全问题;不然须要采纳同步的体式格局防止线程安全问题,如与volatile症结字一同运用等。
static症结不能润饰局部变量,包含实例要领和静态要领,不然就会与static症结字的初志-同享相违犯。
3 润饰要领
用static症结字润饰的要领称为静态要领,不然称为实例要领。经由过程类名.要领名挪用,但须要注重静态要领能够直接挪用类的静态变量和其他静态要领,不能直接挪用成员变量和实例要领(除非经由过程对象挪用)。
class D { static { i = 2; System.out.println("D : 静态代码块"); } static final int i; int j; static void method() { System.out.println(i); System.out.println(new D().j); method1(); new D().method2(); } static void method1() { System.out.println(i); } void method2() { System.out.println(i); } }
注重:既然类的实例要领须要对象挪用才接见,而静态要领直接经由过程类名就可以接见,那末在不斟酌布置服务器的状况下,一个类是怎样最先实行的呢?最大的能够就是经由过程“类名.静态要领”启动Java,而我定义那末多静态要领,JVM又是怎样晓得主进口呢?
也许,你想到了main要领。
没错,就是main要领被Java范例定义成Java类的主进口。Java类的运转都由main要领开启:
public static void main(String[] args) { for (String arg : args) { // 参数由外部定义 System.out.println(arg); }}
但注重main并非Java症结字,它只是一个划定的递次进口的要领名字;别的main要领能够重载。
注重:static症结字虽然不能润饰一般类,但能够用static症结字润饰内部类使其变成静态内部类。static症结字自身的寄义就是同享,而Java类加载到JVM内存的要领区,也是线程同享的,所以没必要用static症结字润饰一般类。
4 静态导入
在用import导入包或许类时,能够用static润饰包名或许类,示意静态导入。静态导入能够与动态导入放在一同比较来加深明白。
动态导入是当你递次运转时须要new一个不在此包中的类的对象时,才会依据全途径类名加载类;而静态导入则是跟着类的加载而加载静态导入的类,所以它是提早导入的。
public class StaticTest { static void method1() { System.out.println("static method1"); } static void method2() { System.out.println("static method2"); } }
静态导入:
import static com.starry.staticImport.StaticTest.method1; public class Client { public static void main(String[] args) { method1(); // StaticTest.method2(); } }
注重method1()是静态导入,所以能够不须要经由过程类名接见;而method2()没有导入,则须要经由过程类名挪用。那末什么时刻须要静态导入呢?
静态导入常用于静态要领以及含有静态要领的类,罗列类等的导入,能够在编译阶段肯定导入类的信息或许要领信息。
static症结字的瑕玷
封装是Java类的三大特征之一,也是面向对象的重要特征。由于不须要经由过程对象,而直接经由过程类就可以接见类的属性和要领,这有点损坏类的封装性;所以除了Utils类,代码中应当只管罕用static症结字润饰变量和要领
以上就是static症结字有什么作用的细致内容,更多请关注ki4网别的相干文章!