static
static关键字 -- 是一个可选修饰符,它本身的含义叫做“静态”。 它不仅只能修饰方法,它也可以修饰:属性、代码块、内部类 。不能修饰构造方法。
static 与 非static 的属性
在一个类当中,属性也可以选择使用static进行修饰。
一、语法上的对比:
有static
1、有static修饰的属性可以用"类名."的方式直接访问,也可以通过“对象.”的方式进行访问(但第二种方式,不推荐)。
2、用static修饰的属性,是全类的所有对象共享一个值,无论是该类的哪个对象把这个值改了,那么大家的值都跟着变。
非static
1、非static修饰的属性是只能用“对象.”的方式访问;
2、非static修饰的属性是每个对象身上有一个该属性的变量,存放了该对象该属性的值。
从两者的第2点语法对比,我们领会Java语法设计者的设计意图。之所以让static修饰的属性能够用“类名.”的方式去访问,不是为了让我们方便,而是为了体现这个属性是全类共享的。而非static修饰的属性用"对象."的方式去访问,是为了清楚的表达到底要操作是哪个对象的该属性。 在一个类当中,能够用static修饰的属性是不多见的,通常都需要在某个特定的问题域限制当中才找得到。static才是特例,通常都是非static的属性。
根据经验,只有常量,我们能够不动脑袋直接设计为static
原因:
1、常量属性的值是在类的定义中给定的,每个对象身上都是同样的值(常量也不能改);所以没有必要在每个对象身上存放一份,只需要全类共享一个就可以了。
2、常量属性的值在类定义中给定以后,外部也没有更改的权利,所以可以不用保密,直接public公布给外部看;
3、所以,通常常量属性的修饰符是:public static final的。
千万不要为了方便去把属性设计为static,一定要找到全类共享一个值的属性才做这种设计。
二、内存上的区别:
1、存放的位置不同
非static修饰的属性是在对象本身身上,也就是在堆当中; static修饰的属性没有存在对象身上,也就不是在堆当中;而是单独作为类的共享信息存放在一个叫做“静态区”的内存空间里;一个类的一个static属性只划分一个存放空间。
2、该属性在内存中产生的时机不同
非static属性实在产生对象的时候,在内存中产生
static的属性是在 加载期 产生与内存中
两个凡是:
1、凡是用static修饰的内容,都是表示它与对象无关,只与类相关; 所以:用static修饰的属性,我们又叫做“类属性”/“静态属性”, 没有static修饰的属性,我们一般叫做“成员属性”
2、凡是用static修饰的内容,都会在加载期加载并执行。
static 和 非static修饰的 方法
一、在语法上的对比:
有static的方法:
1、在调用该方法的时候,可以通过“类名.”的方式来访问,也可以通过"对象."的方式来访问;只不过第2种方式不推荐,但不会报错;
2、在方法的内部实现中,静态方法只能调用本类的静态属性 或 静态方法; 之所以不能调用的原因:
原因1:静态方法是通过"类名."的方式调用,这个时候方法内部是没有当前对象这一目标,也就是说没有“this”,所以无法确认这里访问的非静态属性或方法到底是哪个对象的。 --- 这是站在面向对象的设计思想来表达的;
原因2:当我们在进行类的编译和加载的时候,在进行加载的顺序划分时,JVM都是首先加载静态的,然后再加载非静态的。如果在加载静态内容时,发现里面有非静态的调用,这个时候JVM是不认识这些非静态内容的,因此报错。反过来,在加载非静态的方法时,由于静态内容已经加载过了,所以JVM认识,因此通过。
非static的方法:
1、在调用该方法的时候,只能通过“对象.”的方式访问。
2、在方法的实现内部,即可以操作本类的静态属性和静态方法,也可以调用到本类的非静态属性和非静态方法;
这样的设计同样表明了用static修饰的方法是跟对象无关的;非static的方法是一定要确定到底是哪个对象去做这件事情。所以,用static修饰的方法又被称之为“类方法”或“静态方法”;非static修饰的方法被称为“成员方法”。
二、设计上的区别:
我们要把工具类的工具方法,设计为static的;其他的都是非static的。
static 一定不能用来修饰 构造方法
因为构造方法就是用来创建对象的,而static天生就是用来表示与对象无关。
static 和 非static修饰 初始化块
对初始化块的简单认知
初始化块的语法非常简单,就是直接在类里面,打上一对"{}",然后在"{}"里面书写代码。
它从外观形式上非常像一个没有方法声明,只有方法实现的特殊语句块。在它内部,我们可以书写任意指令语句,包括:输入输出、变量声明、运算表达、流程控制; 由于这个代码块是没有方法声明的,也不能接受参数和返回,所以很明显它是不能够在类的外部随意调用的。 它的执行只能是在一个特定的时间点运行。 什么时候呢? 产生对象的时候,所以它也被称之为“实例初始化块”。每产生一个对象,就会被执行一次。
初始化块也分static 和 非static的
前者也叫“静态初始化块”,后者叫做“实例初始化块”
"静态初始化块"是在加载类的时候被执行的,而一个类在JVM当中只需要加载一次,所以它是首先被执行,且以后无论产生多少对象,甚至不产生对象,也不再被执行。 “实例初始化块”是在产生对象的时候被执行,且产生多少个对象就会被执行多少次。
如果说“实例初始化块”的执行时机和次数与构造方法有一定的重叠,导致它的使用量很少。但是“静态初始化块”由于其独特的执行时机和执行次数,导致它是没有被替换的可能的。
很多资源的操作,包括开启呀,预加载呀,都是一次性完成的,没有必要每new一个对象就做一次,而且很多时候我们会把做这些动作放到程序的加载期而不是运行期,这是为了提升程序的运行速度。
静态初始化块也满足两个凡是:
1、与类有关;
--- 类加载的时候被执行
与对象无关;
--- 不能在其内部访问对象的非静态内容,没有this当前对象,与产生对象与否无关。
2、凡是用static修饰的内容,都会在加载期加载并执行。