static
整理一下有关java关键字 static的用法。
先来看一下《java编程思想》中有关static的说明:
我们从以下几个角度来分析一下static:
1. static的作用是什么?
想一下我们一般调用其他类中的变量和方法是怎么操作的?是不是都要先new一个对象实例出来,接着才能操作对象中的变量和方法,static的目的正是为了不创建对象的情况下,也能使用变量和方法。
2. static可以用来修饰哪些东西?
(1) 修饰类的成员变量,常和final用来一起定义静态常量。
(2)修饰类的成员方法,静态方法不依赖于对象,所以直接通过类就可以进行访问。
扫描二维码关注公众号,回复: 1706286 查看本文章(3)修饰代码块,用来优化程序性能。
3. 调用限制。
在静态方法内部不能访问非静态方法和非静态变量。但是非静态方法内部没有这个限制。
4. 用静态工厂代替公有构造器的优缺点。
除了抽象类和接口类意外,每个类都会有自己的和类同名的构造函数,我们的实例化new的过程,其实也就是调用了类的构造函数的过程。用静态工厂的方法完全可以代替公有构造器,相比较有以下三个优点(具体解释可以参考工厂模式博客):
(1)具名
(2)环保
(3)多子
举个例子看一下:
java基本数据类型中的布尔值,内部就有类似的实现,看下内部的源码:
Boolean的构造函数:
public Boolean(boolean value) { this.value = value; }Boolean中的静态方法:
public static Boolean valueOf(boolean b) { return (b ? TRUE : FALSE); }测试类:
package com.ljw.StaticTest; /** * Created by liujiawei on 2018/6/22. */ public class TestStatic { public static void main(String[] args) { Boolean b = new Boolean("true"); Boolean.valueOf("true"); } }可以看到两种方式最终都实现了一样的目的,获得了一个布尔类型的变量。通过静态方法的valueOf()声明的变量是不是更加直观些呢?
5. static代码块,构造函数以及成员变量的初始化顺序。
在一个类的加载过程中,不同部分的加载顺序不同的,通过代码实例,一起来看下这几个的加载顺序;
父类:package com.ljw.StaticTest; /** * Created by liujiawei on 2018/6/22. */ public class Father { A a = new A("FATHER"); static { System.out.println("父类静态代码块"); } public Father(){ System.out.println("父类构造函数"); } }
子类:
package com.ljw.StaticTest; /** * Created by liujiawei on 2018/6/22. */ public class Son extends Father { public static String sonName = "son"; A a = new A("SON"); static { System.out.println("子类静态代码块"); } public Son(){ System.out.println("子类构造函数"); } }
第三方:
package com.ljw.StaticTest; /** * Created by liujiawei on 2018/6/22. */ public class A { static { System.out.println("A的静态代码块"); } public A(String str){ System.out.println("A的构造函数" + "===" + str); } }
测试类:
package com.ljw.StaticTest; /** * Created by liujiawei on 2018/6/22. */ public class TestStatic { public static void main(String[] args) { new Son(); } }
运行结果:
结果和你想的是一样的么?不是的也没有关系,我们一起来分析下这个加载的过程。
首先,main是主函数的入口,加载Son类,发现Son是继承的Father类,转而加载Father类,发现Father类中静态代码块,优先加载父类的静态代码块,首先输出“父类静态代码块”,加载完父类的静态代码块以后,加载子类的静态代码块,输出“子类静态代码块”,接着继续加载父类中的非静态内容,加载A类,A类中的静态代码块被优先执行,输出“A的静态代码块”,接着A类执行的构造函数,输出“A的构造函数===FATHER”,父类的静态内容加载完毕,加载构造方法,输出“父类构造函数”,父类加载完毕,加载子类中的非静态内容,因为静态代码块中的内容只会被加载一次,保存在内存中,所以直接执行A类的构造函数,输出“A的构造函数===SON”,最后加在子类的构造函数,输出“子类构造函数”。
以上就是整个的分析过程,总结一下就是:
(1)静态内容》非静态内容》构造方法,
(2)父类的静态代码》子类静态代码》父类非静态内容》父类构造方法》子类非静态内容》子类构造方法。
理解不到位之处,还请指出一起学习。
参考博客: https://www.cnblogs.com/starhu/p/5150241.html