一,static关键字
当申明为static型的时候,意味着此域或者方法不会与包含它的实例联系在一起,也就是说,即便没有创建某个类的任何对象,也可以调用static域或者方法。
1,static域初始化的问题:
一般来说,类的代码在初始化时才加载(即创建第一个对象),但当访问static域或者方法时,包含该static域或者方法的对象也会被加载。
构造器是一个隐式的static方法,所以类在任何static型的方法或者域使用时,就要被加载。
比如每个类的main方法,由于是static型的方法,所以在main()函数被使用时,该类就被加载了。
看下面这段代码就能很清楚的了解类的整个初始化过程
private int k = printInit("kkkkkk");
public StaticTest()...{
System.out.println("k = " + k);
System.out.println("j = " + j);
}
private static int x2 = printInit("x2");
public static void main(String[] args) ...{
// TODO Auto-generated method stub
System.out.println("StaticTest");
StaticTest s = new StaticTest();
}
}
class Insert ... {
private int i = 9;
protected int j;
Insert()...{
System.out.println("i = "+ i + ", j ="+ j);
j = 39;
}
private static int x1 = printInit("x1");
static int printInit(String s)...{
System.out.println(s);
return 47;
}
} /** */ /**Output
*x1
*x2
*StaticTest
*i = 9,j = 0
*k = 47
*j = 39
*/
由此可见整个加载过程是这样的:首先执行main()函数,由于是static型所以加载该类的static型域,如果发现了有基类,则先加载基类的static型域。而后执行main()方法下面的指令,如果创建了类的对象(光创建不行,一定要new赋值),则加载类的构造函数(导出类构造器的主体最后调用),如果有基类,先加载基类的构造函数。然后再按申明顺序调用成员的初始化方法。其他类型的变量引用到才会被加载。
2,static关键字需要注意的地方
a,static方法里面没有this方法。也就是说想在其内调用对象的方法只有一种办法,在静态方法内创建对象,并对对象调用方法或者域。
c,无论创建多少个对象,静态数据都只占用一份内存,只会被初始化
b,非静态方法中可以调用静态方法。
二,final关键字
final型方法不能被覆写(所有private型方法默认是final型);final型类不能被继承。
final型域专门拿出来说说。
1,final型域只占一段不能改变的存储空间,一旦final型对象被引用且被指向一个对象,则无法指向另一个对象。
如final value v1 = new Value(1);则v1 = new Value(2);就会报错。
2,final型域定义时就要赋值或者在构造函数的时候赋值,其他情况皆不可赋值。如果是在构造函数时赋值,可以被多次初始话(比如重载构造函数,两次都对一个final型域初始化是可以的!!)。
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;
public class FinalTest2{
final double PI = 3.14 ; // 在定义时便给址值
final int i; // 因为要在构造函数中进行初始化,所以此处便不可再给值
final List list; // 此变量也与上面的一样
FinalTest2(){
i = 100 ;
list = new LinkedList();
}
FinalTest2( int ii,List l){
i = ii;
list = l;
}
public static void main(String[] args){
FinalTest2 b = new FinalTest2();
b.list.add( new FinalTest2());
// b.i=25;
// b.list=new ArrayList();
System.out.println( " I= " + b.i + " List Type: " + b.list.getClass());
b = new FinalTest2( 23 , new ArrayList());
b.list.add( new FinalTest2());
System.out.println( " I= " + b.i + " List Type: " + b.list.getClass());
}
} /** Output
*I=100 List Type:class java.util.LinkedList
*I=23 List Type:class java.util.ArrayList
*/
三,final型和static型数据的一些比较
final型表示不能重复加载,static表示只能初始化一次,final static型表示常量,通常用大写表示。
final数据,常量,在定义后不可更改,但是仅针对当前次的new(),这与static不同,static数据在对象被创建之后,就不可更改,这可以参考以下小片断
import
java.util.
*
;
public class Final { static Random random = new Random(); private final int i1 = random.nextInt( 5 ); private static final int i2 = random.nextInt( 9 ); public static void main(String[] args) { Final f1 = new Final(); System.out.println(f1.i1); // a System.out.println(f1.i2); // b Final f2 = new Final(); System.out.println(f2.i1); // c System.out.println(f2.i2); // d } } 输出结果为,b和d是相同的,a和c一般是不同的(在极微概率下,他们可能相同),static数据,只要对象被创建过,值就是静态的,但是可以更改. 但是,当final数据为对象引用时,不可更改的仅仅为对于对象的引用不可改变,即你不能变为对另一个对象的引用,但是,你仍然可以对对象进行改变,包括数组 切记,final只是不能更改,new()几次,值可以为不同的值;static只要对象被创建了一次,甚至在对象没有被创建的时候都可以使用,而且多个对象共用一个,但是,可以被更改 当方法中的参数被指明为final,参数无法被修改,你只能读。 |