9/03/2010

Java中的static关键字和final关键字

static关键字
基本思想是指定一块固定的存储区域来存储相应的对象或变量。
在两种特殊情况下应该用static:
    一种是为了保证只存储一份特定的数据 - 无论多少对象,甚至有无对象,该数据就在那里,但对象可以改变该数据。
    另一种是需要一种特殊的方法,它和这个类的对象无关,无须创建对象即可使用。譬如说System.currentTimeMillis()。但这也造成了在static方法中不能访问非static的方法和数据。因为在没有这个类的实例的情况下,非static的方法和数据都是不存在的。

static就是这么简单,两种情况,一种是数据唯一,一种是无须实例调用方法。

final关键字
它最一般的意思就是声明“这个东西不能改变”。之所以要禁止改变,有可能是两方面的因素:设计或效率。

 final数据
    如果final修饰一个基本数据类型,则表明该数据不可改变,只能赋值一次。
    如果修饰一个对象句柄,则表示该句柄只能指向这个对象,永远不能指向另一个对象。然而对象本身是可以改变的。
   空白final
     在声明的时候并未得到初始值,但是编译器会确保它在使用前被赋值 - 要么在定义字段使用一个表达式,要么在每个构建器中保证final字段被赋值。

 final方法
    两方面的考虑:第一是为方法“上锁”,防止任何继承类改变它的本来含义。
    第二是程序执行的效率 - 编译器会优化final方法。
    这里有一点要注意的地方,类内所有private方法都自动成为final。由于我们不能访问一个private方法,所以它绝对不会被其他方法覆盖。可以为一个private方法添加final指示符,但却不能为那个方法提供额外的含义。
    这一问题会造成混淆。因为,如果你试图覆盖一个private方法(隐含是final的),似乎是奏效的,而且编译器也不会报错。但是,“覆盖”只有在某方法是基类的接口的一部分时才会出现。既然一个方法被设置为private,则它不可能是基类的接口的一部分。所以这里的覆盖就是一个伪命题。

 final类
    被final修饰的类不能被继承。String就是这样的类。


---------------------分界线----------------------------

有一个疑问:有人说用static final修饰可以作为全局变量来使用,但这个全局变量的修改只能是通过修改程序代码实现,而不能通过读入外部数据来实现。
    因为final要求该变量要么在声明的时候被赋值,要么在构建器中赋值。
    首先在声明的时候赋值,要做到改变全局变量就必须更改程序;
    如果在构建器中赋值,就注定发生错误。因为static关键字要求该变量和实例无关,即在运行构建器之前,这片空间已经被分配并赋值,而在构建器里再进行赋值的话就是第二次赋值,与final关键字的特性矛盾。


感慨一下,Thinking in Java确实是一本好书!本文的很多内容是出自Thinking in Java.