概述
简单来说static是用来方便在没有创建对象的情况下直接通过类名去调用类的方法或变量。
使用场景
1.static变量也称为静态变量,它的对立面是非静态变量,区别是静态变量只在类初次加载时会被初始化且在内存中只有一个副本是能被所有对象所共享的。
2.static方法也称为静态方法,对于静态方法来说它不依赖于任何对象所以在静态方法中是不能访问类的非静态成员变量及方法的,因为非静态成员变量和方法必须是由具体的实例对象去调用。因此它和this(依附于实例对象) 是无缘的,但在非静态方法中可以用静态成员变量和方法。举个最常见的例子static方法就是main方法了为什么它必须是static的,因为main方法是一个程序的入口,在没有创建任何对象时只能通过类名来访问。
3.static修饰类,普通类是不能声明为静态的,但可以用来修饰内部类
public class Test{
public static class Inner{
Inner(){
System.out.println("我是一条内部类咸鱼");
}
public void InnerMethod() {
System.out.println("我想游泳");
}
}
public static void main(String[] args){
//直接访问内部类
Inner inner = new Test.Inner();
//调用方法
inner.InnerMethod();
}
}
/**输出
**************************我是一条内部类咸鱼*********************
**************************我想游泳******************************
*/
如果不用static修饰Inner类,则只能通过new 一个实例去调用。
4.静态导包,常用于静态方法以及含有静态方法的类,枚举类等的导入,可以在编译阶段确定导入类的信息或者方法信息。
public class Test {
public void test() {
System.out.println("静态导包。。。");
}
}
import static com.fac.Test.test;
public class Test2 {
public static void main(String[] args) {
test(); // 静态导包。。。
}
}
5.static代码块,用来当做静态代码块优化性能。static代码块可以有多个,在类初次被加载时会按照顺序去加载每个代码块且只会执行一次。(可放在除方法外的任何地方)执行顺序如下:
父类静态变量
父类静态代码块
子类静态变量
子类静态代码块
父类普通变量
父类普通代码块
父类构造函数
子类普通变量
子类普通代码块
子类构造函数
例证:
public class Test2 extends Test1{
static{
System.out.println("咸鱼2号");
}
public Test(){
System.out.println("构造咸鱼2号");
}
public static void main(String[] args) {
new Test2();
}
}
class Test1{
static{
System.out.println("咸鱼1号");
}
public Test1(){
System.out.println("构造咸鱼1号");
}
}
// 咸鱼1号
// 咸鱼2号
// 构造咸鱼1号
// 构造咸鱼2号
别的就不一一列举了有兴趣的可以自己试试。
深入分析
上面只是基本的使用场景,下面从jvm内存角度解析一下
简单描述java 运行时的数据区域
java堆:
1、存的是全是对象,每个对象都包含一个与之对应的class的信息。(class的目的是得到操作指令)
2、jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身
栈区:
1.每个线程包含一个栈区,栈里只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在堆区中
2、每个栈里的数据(原始类型和对象引用)都是私有的,其他栈不能访问
3、栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)
方法区:
1、也称静态区,包含所有的class和static变量,和堆一样被所有的线程共享。
2、包含的都是在整个程序中永远唯一的元素,如class,static变量。
这样就很逻辑就很清晰了,静态变量和方法都是在方法区(静态区),new的对象 和成员变量是在堆中,指向对象的引用都放在栈里。堆中的成员变量、栈里的引用会随着对象的消失而消失 但静态区中的静态变量是所有线程共享且不会消失的。
后续
抽象(abstract)方法能否被static 修饰?
答:不能,抽象方法将来是要被重写的,而静态方法是不能重写的。(重写的首要条件是要有对象)