前言
static这个关键字是属于可选修饰符的一种
目录
成员内部类
用static修饰的内容具备的特点:
1、与对象无关,与类有关;
2、都会在加载期搞点事情。由于是在加载期搞事情,这个时候程序还没有运行,所以程序没有进入动态运行,因此static又被称为“静态”。
可修饰对象:(类里的内容)
属性
属性可以使用static进行修饰;
效果:用static修饰的属性,不再是每个对象身上具有一个,而是全类共享同一个值。
内存:
- 没有static修饰的时候,这个属性是存放在不同的对象身上的;每个对象各自存放一份儿自己的;
- 有了static修饰的时候,这个属性不再存放在对象身上了,而是在数据段的静态区中存放了一份。无论用这个类的哪个对象去访问操作这个属性,都是操作的这同一份。所以,无论是哪个对象去把这个属性值改动了,其它同类对象再去访问也看到被改动了。
那么这个属性是在什么时候产生在内存中的呢?
- 没有static修饰的属性是在new对象的时候产生对象空间中,不去new对象就没有这个属性。
- 有static修饰的属性不用new对象,是在加载期的时候就自动产生了。
public class Student{
public String name;//普通属性
public static int age;//静态属性
}
public class Test{
public static void main(String[] args){
Student stu= new Student();//产生一个stu对象
System.out.println(stu.name);//编译运行成功
System.out.println(stu.age);//编译运行成功
System.out.println(Student .name);//编译即失败
System.out.println(Student .age);//编译运行成功
}
}
语法上:
static修饰的属性可以用" 类名. "的方式直接访问,无需像普通属性一样通过"对象."的方式才能操作。毕竟,全类共享这个值,那么这个类的任何一个对象也是属于这个类的,所以也应该能够看到。
总结:
1、static可以修饰属性;static修饰的属性被称为“静态属性” 或 “类属性”;
2、static修饰的属性全类共享唯一值(与对象无关);表现在所有该类对象都用同一个属性;同时语法上可以直接用类名访问;
3、static修饰的属性是在加载类的时候就会被产生在内存中,所以就算没有对象也能直接访问操作;
4、static的属性一定是那种全类(所有对象)共享一个值的属性,只要有一个对象改动了这个属性的值,该类型的所有对象都被修改了。
static的属性,好比班费,一个同学拿了一百,其他同学看到的班费就都少了一百
另外,常量属性不用想,写成:public static final的。
构造
构造方法不能使用static修饰;
因为static修饰的内容是会变成与对象无关的。但是,构造方法的作用就是产生对象,所以它一定是与对象相关的,也就无法用static修饰。
初始化块
可以使用static修饰初始化块,修饰后叫做“静态初始化块”。
普通的实例初始化块,很少用,因为它的执行时机和执行内容是与构造方法有重合的。但是,静态初始化块常常能够看到。
静态初始化块是在加载期加载这个类的时候被执行,且一个类只需要被加载一次,所以它也就只执行一次。
这个特点导致静态初始化块的执行时机是独一无二的,在稍微有点规模的项目当中,都会出现。我们往往把要在执行前的准备工作,写在静态初始化块当中。让程序在运行前先完成这些准备动作。
注意:静态初始化当中只能操作静态的属性(行为),不能操作到非静态的。
静态初始化块是在加载期被执行的,这个时候还没有执行到产生对象的代码,而非静态的内容都是跟对象进行绑定的,所以我们无法在静态代码块中指定this是谁,也就无法告知JVM这些静态属性是哪个对象身上的。
比如: ATM机的用户信息 全类共享 不同的ATM机都可以识别所有的用户信息
行为
行为是可以用static修饰的。
添加了static的行为被称为“静态方法” 或 “类方法”。
普通行为需要使用"对象."的方式访问;静态方法可以用"类名."的方式访问。
注意:在静态方法内部不能访问本类的非静态属性(或方法),因为在静态方法内部没有this。只能操作本类的静态属性(或静态方法)
在加载类当中的内容的时候,加载器会优先加载类的静态内容,然后才加载类的非静态内容。
什么样的方法我们会设计为static的呢?--- 工具类的工具方法才设计为static。
什么是工具类的工具方法呢?就是这个方法的使用者不关注是由哪个对象来完成的这个动作,并且这个行为在完成的过程中也不会对执行对象的任何非静态数据造成影响。
举一个例子: A、博主类有一个行为叫写一篇点赞超过1W的文章;它的实现就是接受参数:文章和点赞,返回点赞对象。 这个时候写文章的行为无论让博主类的哪个对象去完成,效果是没有差异的,甚至调用者也不关注是江小白还是江大白写的。博主写文章行为对于调用者来说就是一个工具,做完了就结束了。所以写文章行为设计为是static的即可。 B、博主类有一个行为叫写一篇点赞超过1W的文章;它的实现就是接受参数:文章和点赞,返回点赞对象。谁写出了点赞超1w的文章,该博主的积分+100分。 这个时候要关注的是哪个博主对象完成的这个行为,就跟对象有关了。所以,就不能用整个博主类去操作,而一定是用某个具体的博主对象,所以写文章行为一定是非static的。 C、先人的代码也是这么设计的,比如:String都有方法是equals,这个方法肯定是非static的。 而Math.random(),这个方法就是static的。这个时候,无论使用哪个Math对象得到的结果都是一样的,也不会改变这个Math对象的任何与对象有关的内容,所以就无所谓了,只要是Math即可。那干脆简单一点,设计成static,直接用“类名.”。