您的位置:首页 > 其它

static和final关键字

2008-06-28 09:31 267 查看
static和final是Java中最常用的关键字,本文介绍它们的所有用法以及含义。

static通常用来修饰类的成员变量和类的方法,它可以用在以下场合:

1.修饰类的成员变量:意味着这个成员变量作为整个类而不是类的某个特定对象而存在,可以通过类名直接引用它们。一个static成员变量对每个类来说都只有一份存储空间,而非static成员变量则是对每个对象有一份存储空间。
2.修饰方法:static方法可以通过类名直接访问。
3.静态导入:静态导入static成员变量和static方法。
4.静态程序块:通常用来做一些初始化,static{}。
5.修饰成员类型:如修饰嵌套类(nested class),嵌套类和普通的内部类的区别就在于static的修饰。普通的内部类不能包含static数据和static属性,也不能包含嵌套类,但是嵌套类可以包含所有东西。注意static不能用来修饰最顶层的类。

下面的代码显示了static的可用之处和不可用之处:
//导入静态成员,不常用
import static java.util.Calendar.AM;
import java.util.HashMap;
public class StaticTest {
//静态成员变量,它只存有一份
private static int i = 123;
private int j = 0;
private static HashMap map = new HashMap();

//静态程序块,用来做一些初始化动作
static {
map.put("userid", "admin");
}
public void printI() {
System.out.println("i=" + i);
}
//静态方法,
public static void s() {
int m = 0;//可以定义非静态变量
staticint n = 0;//错误代码,不能定义静态变量
System.out.println(i);//可以使用静态的成员变量
System.out.println(j);//错误代码,不能使用非静态的成员变量
}
public static void main(String[] args) {
//直接通过类引用静态成员变量和方法
StaticTest.s();
StaticTest.i++;
//test1和test2打印出来的i值一样,因为它只有一份
StaticTest test1 = new StaticTest();
StaticTest test2 = new StaticTest();
test1.printI();//i=124
test2.printI();//i=124
}
}
下面的代码显示了static修饰嵌套类:
public class StaticTest2 {
//普通内部类
class InnerClass {
static int i = 0;//错误代码,普通内部类不能使用静态成员变量
static final int j = 0;//正确代码,常量
}
//嵌套类,与普通内部类的区别在于多了static的修饰
static class NestedClass {
static int i = 0;//正确代码
}
}
final关键字通常表示一个东西是不能改变的,它可以修饰的元素有:

1.修饰数据:通常用来定义常量。对于基本类型,final使数值恒定不变,而对于对象引用,final使引用恒定不变,一旦引用被初始化指向一个对象,就无法把它改为指向另一个对象,然而,对象其本身是可以被修改的。

2.修饰参数:和修饰数据一样。

3.修饰方法:通常用来防止方法被子类覆盖(overriden),一个类中的所有private方法都隐含是final的,因为它无法被子类读取,也就不会被覆盖。另外,编译器针对final方法的调用都采用内嵌(inline)调用,可提高效率,但不是final的主要用途。

4.修饰类:表明该类(class)不能被继承。在final类里,所有的方法都被隐含的指定为final的,因为永远不存在子类,也就不存在子类覆盖一说。final类的字段可以根据个人的意愿选择是或不是final,不论类是否定义为final,相同的规则都适用于final字段。

平日在编程中用的最多的应该是使用final修饰数据,尤其是定义常量。

下面的代码显示了final对各种元素的修饰:
//修饰类,类不能被继承
public final class FinalTest {
//修饰数据,i不能被再次赋值
private final int i = 0;

//修饰方法,该方法不能被子类覆盖
public final void f(String s) {
System.out.println("FinalTest.f");
}
//修饰参数,j不能被重新赋值
public void g(final int j) {
j = 1;//这条语句是错误的
}
}
下面的代码显示了父类不能覆盖子类的final方法:
public class FinalChild extends Final {
//这个方法是错误的,它不能覆盖父类的final方法
public void f(){};
//这个方法正确,重载
public void f(String s){}
}
class Final {
public final void f() {}
}
对于对象引用的修饰容易让人迷惑,看下面的程序:
final int i = 0;
i = 1;//错误的代码,不能重新赋值
final StringBuffer s = new StringBuffer("Java");
s.append("World!");//正确代码,可以改变对象内容
s = new StringBuffer("Hello");//错误的代码,不能给引用重新赋值,它不能指向别的对象
注意代码注释,对整型i的修饰很好理解,给了i初值后,不能再给它其它值。而对于对象引用s,虽然用了final修饰并赋了初值,但依然可以使用s来操纵对象,只不过,不能再将s指向其它对象。

不要以为在定义final数据成员时必须指定初值,也不要以为它只能给一个常数值,它还可以是一个表达式,如下面的代码是成立的:
final int j;
j = 2 * 3;
像上面这种未指定初值的声明final数据成员通常称为空白final。

对于类的成员变量,有无final修饰存在一点区别,对于没有final修饰的成员变量,它们都有一个默认的初值(如整型数据为0),而对于final修饰的成员变量,必须确保它被初始化。看下面的程序:
public class TestFinal {
private int i;//默认值为0。如果是private final int i;程序就会报错
public void print() {
System.out.println(i);
}
}
如果使用final修饰i,程序就会出错,因为它未被初始化。如果想用final修饰的同时又不想在声明时初始化,则可以在构造函数中赋值。如下面的程序是正确的:
public class TestFinal {
private final int i;
public TestFinal () {
i = 0;
}
public void print() {
System.out.println(i);
}
}
一个既是static又是final的字段只占据一段不能改变的存储空间。 带有恒定初始值(即,编译时常量)的static final基本类型全用大写字母命名,并且字与字之间用下划线隔开。如java.lang.byte类里对byte类型的最小值定义:
public static final byte MIN_VALUE = -128;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: