只要是有学过Java的都必定知道static,也必定能多多少少说出一些做用和注意事项。若是已经对static了如指掌的请点击关闭按钮,看下去也只是浪费您宝贵时间而已。这篇随笔只是我的的习惯总结。java
有时候咱们并不想去new一个对象,只是单纯的想要调用一个函数,而且但愿这个函数不会与包含它的类的其余对象有所关联。说得通俗点,即便没有建立对象,也能经过类自己来调用函数。编程
被static修饰的变量属于类变量,经过字面意思就说明了这个变量的归属(类),与之相对的是没有被static修饰的成员变量,也称为实例变量,说明这个变量是属于某个具体的对象。函数
public class StaticDemo { private static int i = 50; private int j = 60; public static void main(String[] args) { StaticDemo staticDemo = new StaticDemo(); StaticDemo staticDemo1 = new StaticDemo(); //即便建立两个对象,也都指向同一存储空间 System.out.println(staticDemo.i); System.out.println(staticDemo1.i); //改变值 staticDemo.i = 52; System.out.println(staticDemo1.i); staticDemo.j = 65; staticDemo1.j = 70; System.out.println(staticDemo.j); System.out.println(staticDemo1.j); } }
输出测试
50 50
52 65 70
经过上面的实例,咱们很快看出他们的区别this
说到静态函数,就不得不提Java另外一个关键词this,指的是当前的引用。意思是调用这个函数的对象,这意味着和static修饰的函数水火不容。被static修饰的函数,不能出现this关键字,不然便会报错。spa
去掉this,分别调用i或者j,会发现静态函数调用非静态资源时出错。这是为何?从JVM加载机制角度来讲,静态资源(被staitc修饰)是类在初始化的时候就加载的,而非静态资源是new的时候加载的。类的初始化是早于new的,加载了say()的函数时,它并不认识 j 这个成员变量,但对于非静态函数来讲,当它加载时,静态资源已经加载完毕,因此它是认识 i 这个静态资源的。咱们总结一下static修饰函数时的特色code
如今,咱们也能知道main函数为何必须是static的,由于程序在执行main函数时候,没有建立任何对象,只是经过类名来访问。对象
《Java编程思想》提到“即便没有显示地使用static关键字,构造器实际上也是静态方法”。我至今不能确认构造器是否是静态函数,我的更偏向于不是。缘由待会再阐述,先看个实例blog
public class StaticTest { private static int i; private int j; public StaticTest(int i,int j)
{ this.i = i; this.j = j;
say1() } public void say1() { System.out.println("you age is" + i); System.out.println("you age is" + j); } public static void main(String[] args) { StaticTest staticTest = new StaticTest(4,5); StaticTest staticTest1 = new StaticTest(10,69); System.out.println(staticTest.i); System.out.println(staticTest.j); System.out.println(staticTest1.i); System.out.println(staticTest1.j); } }
输出资源
you age is4
you age is5
you age is10
you age is69
10
5
10
69
实例中,确实改变了 i 的值,也符合静态资源的定义,只有一份存储空间。但构造器里用了this,与我前文所说的static属于类,不属于任何对象,this属于当前引用对象互相矛盾,而且构造函数还能够调用实例函数。一脸懵逼,这也是让我感到困惑而且认为构造函数不是静态函数的地方。若有周知,留言解惑,感谢。
private static int i;
static { i = 5; }
静态块是static的重要应用之一,无函数名、做用域、返回值以及参数,静态代码块与静态变量和静态函数同样,不论类被调用多少次,该区域代码只在类初始化时第一次时执行一次,而且严格按照静态资源的定义顺序执行加载,与静态函数区别在于一个主动一个被动。
{ System.out.println("我是静态块."); }
非静态块,一样无函数名,做用域,返回值以及参数,非静态代码块会在每次类被调用或者被实例化时执行。
public class StaticTest extends Father { public StaticTest() { System.out.println("我是StaticTest的构造函数"); } { System.out.println("我是StaticTest的非静态块"); } static { System.out.println("我是StaticTest的静态块"); } public static void main(String[] args) { new StaticTest(); new StaticTest(); } } class Father { public Father() { System.out.println("我是Father构造函数"); } { System.out.println("我是Father非静态块1"); } { System.out.println("我是Father非静态块2"); } static { System.out.println("我是Father静态块"); } }
输出
我是Father静态块
我是StaticTest的静态块
我是Father非静态块1
我是Father非静态块2
我是Father构造函数
我是StaticTest的非静态块
我是StaticTest的构造函数
我是Father非静态块1
我是Father非静态块2
我是Father构造函数
我是StaticTest的非静态块
我是StaticTest的构造函数
加载顺序 :父类静态块 > 子类静态块 > 父类非静态块 > 父类构造函数 > 子类非静态块 > 子类构造函数
静态代码块以及非静态代码块都会在构造函数前执行,首次访问时,静态代码块会在非静态代码块前执行。
改变main函数
public static void main(String[] args) { }
输出
我是Father静态块
我是StaticTest的静态块
静态代码块在类加载时自动执行,非静态代码块是在建立对象时自动执行的代码,不建立对象不执行该类的非静态代码块。
静态导入是jdk5引入的新特性,有时咱们在实际应用中,并不须要整个jar包都导入,而只是想使用某部分函数。提升代码的阅读性,更好的理解程序。
import static java.lang.System.out; public class StaticTest { public static void main(String[] args) { out.println("import static测试");
System.out.println("import static测试");
}
}
输出
import static测试 import static测试
会发现,二者输出是没有区别的,可是咱们少写了System. 虽然容许这么使用,但在实际开发中,我不多发现有同事这么作,主要是不利于理解,但好处是若是频繁用这个类,能够少不少的类名。
===============================================================
如发现错误,请及时留言,lz及时修改,避免误导后来者。感谢!!!