<Java SE 详解> static与final使用陷阱-
1、static关键字:可以用于修饰属性,也可以用于修饰方法,还可用于修饰类。
a> static修饰属性:无论一个类生成了多少个对象,所有这些对象共同使用唯一一份静态的成员变量,即静态成员变量是属于类的,而不是某一个特定的对象的。一个对象对该静态成员变量进行了修改,其他对象的该静态成员变量的值也会随之发生变化。
如果一个成员变量是static的,那么我们可以“类名.成员变量名”的方式来使用它(Java推荐使用这种方式访问静态成员)。
b> static修饰方法:static修饰方法叫做静态方法,对于静态方法来说,可以使用“类名.成员方法名”进行访问。
2、静态方法(static method)只能被继承或者是隐藏(hide),而不能被重写(override)。静态方法遵守覆盖或隐藏的特性,而不像实例方法中的重写或覆写特性。在实际开发中很少碰见这种隐藏的使用情况。
详见:http://docs.oracle.com/javase/tutorial/java/IandI/override.html
如下例:
package cn.edu.bupt.staticTest;
public class StaticTest {
public static void main(String[] args) {
N n = new N();
n.output(); //output "N"
System.out.println("-----------------");
M m = new N(); //output "M"
m.output();
}
}
class M {
public static void output() {
System.out.println("M");
}
}
//静态方法可以被继承,可以被hidden,但是不可以被override,在实际开发中很少碰见这种情况.
class N extends M {
//Hide the class method in M, not override
public static void output() {
System.out.println("N");
}
}
3、final关键字:final可以修饰 属性、方法、类。
a> final修饰类:当一个类被final所修饰时,表示该类是一个终态类,即不能被继承;
b> final修饰方法:当一个方法被final所修饰时,表示该方法是一个终态方法,即不能被重写(实例方法)(override)以及(隐藏)(类方法)(hide);
c> final修饰属性:当一个属性被final所修饰时,表示该属性不能被改写,即变量内部的内容不能被改变,对于final类型成员变量,必须要进行显式赋初值,否则会发生编译错误。
例: 二十三-43:00
package cn.edu.bupt.staticAndfinal;
public class FInalTest {
public static void main(String[] args) {
People people = new People();
people.address = new Address(); //final引用变量内所存的对象地址被改变,编译错误
people.address.name = "shanghai"; //所指对象的内容(name)发生改变,但是对象在内存中的地址并未改变
}
}
class People {
public final Address address = new Address();
}
class Address {
public String name = "beijing";
}
说明:
当final修饰一个原生数据类型时,表示该原生数据类型的值不能发生变化(比如说不能从10变为20);如果final修饰一个引用类型时,表示该引用类型不能再指向其他对象了,但该引用所指向的对象的内容是可以发生变化的。
对于final成员变量的各种错误见 二十四-02:00
final成员变量初始化方式:
a> 在定义final变量的时候同时赋初值;
b> 在定义final变量的时候不赋初值,但是需要在该类中的所有的构造方法中给该final类型的成员变量赋初值。 二十四-06:30
4、static代码块:静态代码块。静态代码块先于构造方法执行,是在类被加载入Java虚拟机的时候执行static代码块的。
如下例:
package cn.edu.bupt.staticAndfinal;
public class StaticTest2 {
public static void main(String[] args) throws Exception {
//Class<?> classType = P.class;
//Object o = classType.newInstance();
new S();
}
}
class P {
static {
System.out.println("P static block");
}
public P() {
System.out.println("P Constructor");
}
}
class Q extends P {
static {
System.out.println("Q static block");
}
public Q() {
System.out.println("Q Constructor");
}
}
class S extends Q {
static {
System.out.println("S static block");
}
public S() {
System.out.println("S Constructor");
}
}
最终输出的结果是:

解释:
当new S()的时候首先需要加载类S,然后才是实例化S类,即S的静态代码块先于构造方法执行;
但是S是Q的子类,因此需要加载Q,Q是P的子类,又需要加载P,因此需要执行P的静态代码块,再Q,再S;
S的静态代码块执行完成,随后开始执行S的构造方法;
S是Q的子类,Q是P的子类,因此构造方法执行顺序为PQS,这样合起来执行顺序为 PQS - PQS。
5、不能在静态方法或静态代码块中使用this关键字。
浙公网安备 33010602011771号