static与final的区别

文章来源于《传智特刊》正文,如需转载请注明出处。
http://bbs.itcast.cn/forum.php?mod=viewthread&tid=17654&reltid=24281&pre_thread_id=0&pre_pos=7&ext=
导语: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;//可以定义非静态变量
        static int n = 0;//错误代码,不能定义静态变量
       System.out.println(i);//可以使用静态的成员变量
       System.out.println(j);//错误代码,不能使用非静态的成员变量
    }
    public static voidmain(String[] args) {
        //直接通过类引用静态成员变量和方法
        StaticTest.s();
        StaticTest.i++;
        //test1和test2打印出来的i值一样,因为它只有一份i=123
        StaticTest test1 = newStaticTest();
        StaticTest test2 = newStaticTest();
        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.修饰方法:通常用来防止方法被子类覆盖(override),一个类中的所有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(Strings) {
       System.out.println("FinalTest.f");
    }
    //修饰参数,j不能被重新赋值
    public void g(final int j){
        j = 1;//这条语句是错误的
    }
}
下面的代码显示了父类不能覆盖子类的final方法:

public class FinalChild extends FinalTest2 {
    //这个方法是错误的,它不能覆盖父类的final方法
    public void f(){};
    //这个方法正确,重载
    public void f(String s){}
}
class FinalTest2 {
    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 = 1 * 2;
像上面这种未指定初值的声明final数据成员通常称为空白final。
对于类的成员变量,有无final修饰存在一点区别,对于没有final修饰的成员变量,它们都有一个默认的初值(如整型数据为0),而对于final修饰的成员变量,必须确保它被初始化。看下面的程序:
public class FinalTest3 {   
    private int i;//默认值为0。如果是privatefinal int i;程序就会报错
    public void print() {
        System.out.println(i);
    }
}
如果使用final修饰i,程序就会出错,因为它未被初始化。如果想用final修饰的同时又不想在声明时初始化,则可以在构造函数中赋值。如下面的程序是正确的:
public class FinalTest4 {   
    private final int i;
    public FinalTest4 () {
        i = 0;
    }
    public void print() {
        System.out.println(i);
    }
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值