修饰符:
1)final, abstract
2)transient、synchronized、native、strictfp
3)static
首先我们介绍用于方法的修饰符,接着介绍应用于示例变量的修饰符,最后介绍static应用于变量和方法时怎样工作。
final方法
final关键字能防止方法在子类中重写,它常常用于执行方法的API功能。例如,Thread类具有一个名为isAlive()的方法,他检查线程是否仍然为活动的。但是如果扩展Thread类,确实没有任何方法能够正确地实现该方法(一个原因是它使用本地代码) ,因此,设计者将其设计成final类。就像不能子类化String类一样(因为需要能够信任String对象的行为),我们也不能重写核心类库中的很多方法。“不能重写”这一限制提供了安全保障,但是仍然应该很小心地使用它。组织子类重写方法会失去面向对象的很多优点,包括多态实现的可扩展性。典型的final方法声明如下:
扩展SuperClass是合法的,因为该类本身没有标识为final。但是,不能像下面的代码那样试图重写final方法showSample():
上面的代码将会发生编译错误。
final变元
方法的变元是方法声明中出现在两个圆括号之间的变量声明。带多个变元的点典型方法声明如下所示:
方法的变元实质上与局部变量相同。在前面的例子中,变量fileNumber和recordNumber 都将遵守应用于局部变量的规则。这意味着它们也可以带修饰符final:
在这个例子中,将变量recordNumber声明为final,这当然意味着不能在该方法中修改它。这时,“修改” 是指为该变量重新赋一个新值。换句话说,final变元必须保持与传递给方法是参数锁具有的值相同。
抽象方法
抽象方法是一个已经声明了(声明成abstract) 但没有实现的方法。换句话说,该方法没有包含任何功能代码。也就是,它没有方法体。当要求子类必须提供实现时,可以将方法标识为abstract。例如,如果编写一个具有goUpHill()方法的抽象类Car,你可能希望Car的每个子类都必须定义其自己的、专属于某种车辆类型的goUpHill()行为。
注意,抽象方法是以分好而不是波形括号结尾的。在没有显示声明为abstract的类中,哪怕只有一个抽象方法也是非法的!
请看下面的非法类:
但是,可以使抽象类不带抽象方法。下面的代码能够编译:
在上面的例子中,goodMethod()不是抽象方法。有3条不同的线索能让你判断出它不是抽象方法:
1. 该方法为标识abstract
2. 方法声明包含波形括号,而不是以分号结束。换句话说,方法具有方法体。
3. 方法提供了实际的实现代码。
任何扩展抽象类的都必须实现超累的所有抽象方法,除非子类也是抽象的。规则如下:
抽象类的第一个具体子类必须实现超类的所有抽象方法。
“具体” 只不意味着它是非抽象的。因此,如果有一个抽象类扩展另一个抽象类,则该抽象子类不需要为继承的抽象方法提供实现。但是,迟早有人要建立非抽象子类(也就是可以被实例化的类),该子类必须实现来自继承树的所有抽象方法。下面的例子演示了具有两个抽象类的具体类的继承树:
那么,其中Mini类有多少个方法呢?3个。它同时继承getType()方法和doCarThings() 方法,因为他们是公共的和具体的(非抽象) 。但是,由于父类Vehicle中goUpHill()抽象的。并且在Car中永远不会被实现(因此他保持是抽象的),所以,这一意味着Mini类——作为Vehicle下面的第一个具体类——必须是想goUpHill()方法。换句话说,Mini类不能将责任(抽象方法实现)推卸给继承书中的下一个类。但是类Car可以这样做,因为和Vehicle一样,Car也是抽象的。
要注意那些部位超类的抽象方法实现的具体类。下面的代码将无法编译:
类B不能编译,因为它没有实现继承的抽象方法foo()。尽管类B中的foo(int I) 方法好像是超累抽象方法的一种实现,但它只是一个重载方法(标识符相同,但变元不同的方法),因此,它没有完成超类的抽象方法的要求。
一个方法永远、永远、永远不能同时标志为abstract和final,或者同时标识为abstract和private。
思考一下:抽象方法必须被实现(这是指意味着要被子类重写) ,而final方法和private方法永远本鞥被子类重写。
可以这样说,abstract和final修饰符实际上是对立的。private方法不能被子类看到,所以他们也不能被重写,因此不能将其标识为abstract。
最后,你需要了解abstract修饰符永远不能与static修饰符组合使用。本届稍后部分将介绍static方法,但是现在只要记住下面的内容是非法的即可:
它将产生一个错误,你现在应该熟悉它了