1.static是什么
static在java中的意思是“静态的”,什么是静态的?静态的 意味着这个东西和对象无关,和类有关。
2.static作用在变量上
当static作用在变量上的时候,意味着这个变量被这个该类所有的对象共享(同一个hashCode地址),static表示的同一个hashCode,但不是表示该hash地址不可以改变,如果要该hash地址不改变,那是final的作用。看看如下代码:
public class StaticTest {
private static String staticVar = "aaa";
public void changeStaticVar(){
staticVar = "bbb";
System.out.println(staticVar.hashCode());
}
public static void main(String[] args) {
System.out.println(StaticTest.staticVar.hashCode());
System.out.println("==============");
StaticTest test = new StaticTest();
test.changeStaticVar();
System.out.println(StaticTest.staticVar.hashCode());
}
}
//输出结果
96321
==============
97314
97314
由此可以证明,当static修饰变量的时候,它更像是“属于”类的,而不是属于某一个对象的。
3.static作用于方法上
static作用于方法上,和作用于变量上的意义是大同小异的,它更像是“属于”类的,而不是属于某一个对象的。static方法在类实例化对象之前就已经存在。所以,在static方法中是不允许使用非static成员变量或方法的。为什么?因为此时都没有对象,怎么使用对象的方法和变量?看看如下代码:
public class StaticTest {
private String var = "aaa";
public static void changeStaticVar(){
//var = "bbb"; 编译器报错
}
}
思考:main方法也是用static修饰的,它有什么特别之处?其实它的特别之处就是用了static,我以前在学习java的时候,总是想不new对象,直接在main方法里使用该类的其它方法,却永远都是报错,原来就是这个static在作怪。由此更可以看出,在main方法开始的时候,其实没有任何对象被实例出来,所以就没有办法使用非static方法,除非实例化出对象。
那么在反过来呢?在非static方法中能不能使用static变量?当然可以,非static的方法就是给对象调用的吧?对象已经生成了,static变量早已经生成了。
另外,其实类的构造器都是static的。
4.static静态块
static静态块在实际开发中非常有用,它在类加载的时候总是第一个被加载(仅次于静态成员变量),看如下代码
public class StaticTest {
private String var = getVar();
private static String staticVar = getStaticVar();
static{
System.out.println("static静态块");
}
public StaticTest() {
System.out.println("构造方法");
}
public String getVar(){
System.out.println("成员变量var");
return "var";
}
public static String getStaticVar(){
System.out.println("静态成员变量staticVar");
return "staticVar";
}
public static void main(String[] args) {
StaticTest test = new StaticTest();
}
}
//输出结果
静态成员变量staticVar
static静态块
成员变量var
构造方法
其实从输出结果就可以看出 static的特别:就是其独立于对象之外。在对象还没有生成的时候,它们就已经被实例化了。
思考:如果StaticTest类继承了一个和它差不多类,那么实例化对象时,是父类的静态成员变量先实例化?还是子类先?大家可以自行实验。
5.static作用于类
static不能作用于一般的类上,只能作为某一个类的匿名类存在,虽然不知道有什么意义:
public class StaticTest {
static class InnerClass{
}
public static void main(String[] args) {
InnerClass innerClass = new InnerClass();
}
}
6.一个小例子
思考下面这段代码的输出顺序是什么
//父类
public class FatherClass {
private String fs = finit();
private static String fs1 = fstaticInit();
private static String fstaticInit() {
System.out.println("父类静态成员变量初始化!");
return "";
}
static {
System.out.println("父类静态块初始化!");
}
public FatherClass(){
System.out.println("父类构造函数初始化!");
}
private String finit(){
System.out.println("父类成员变量初始化!");
return "";
}
}
//子类
public class InitClass extends FatherClass{
private String s = init();
private static String s1 = staticInit();
private static String staticInit() {
System.out.println("子类静态成员变量初始化!");
return "";
}
static {
System.out.println("子类静态块初始化!");
}
public InitClass(){
System.out.println("子类构造函数初始化!");
}
private String init(){
System.out.println("子类成员变量初始化!");
return "";
}
}
//main
public class Main {
public static void main(String[] args) {
InitClass initClass = new InitClass();
}
}
是不是非常好玩,自己体会,结果如下
1.父类静态 成员变量初始化!
2.父类静态块初始化!
3.子类静态成员变量初始化!
4.子类静态块初始化!
5.父类成员变量初始化!
6.父类构造函数初始化!
7.子类成员变量初始化!
8.子类构造函数初始化!
//序号是自己添加的