3.2 abstract和final修饰符
abstract(抽象的)和final(终态的)是Java的两个修饰符,都可以修饰类。被abstract修饰的类称为抽象类,抽象类是不可使用的,Java体系不允许创建抽象类的类对象,抽象类是作为父类应用的,需要由其他类继承后方可使用。被final修饰的类称为终态类,终态类是不能作为父类使用的,是不允许被其他的类继承的。另外,abstract和final修饰符还可以修饰类中的方法,final修饰符可以修饰类中的变量。
3.2.1 abstract修饰符
abstract修饰符可以修饰类,也可以修饰方法,但是,只能修饰抽象类中的方法。
顾名思义,抽象类在概念上描述的就是抽象世界。例如,动物相对于具体的狗、猫等就是一个抽象的概念;数字相对于具体的整数、浮点数等也是一个抽象的概念。抽象类是一种特殊的类,抽象类的定义方式是在类定义的前面加上修饰符abstract,抽象方法的定义也是类似的。其语法格式为:
与普通类不同的是在抽象类中允许声明类中方法为abstract抽象的,但是抽象方法应为没有方法体的空方法,因为“抽象”,没有具体内容,所以抽象方法为空方法,只是在抽象类中声明有这个方法而已,当使用abstract声明方法时,不能与关键字static、private或final同时使用。
因为抽象类不能创建其类对象,只能作为父类被应用,因此,需要非抽象的子类来继承抽象类,同时在子类中还需要覆盖抽象类中的抽象方法,为该方法填写具体内容(方法体)。
另外,当一个类的定义完全表示抽象概念时,就不应该被实例化为一个对象。例如,Java基础类库中的Number(数字)类就是一个抽象类,只表示数字这一抽象概念,只有作为整数类Integer或实数类Float等的父类时它才具有其意义。
【示例3-15】 描述动物的抽象类的Java演示程序代码。
在抽象类Animal中的普通方法是针对所有动物的,例如操作动物名称、类别等,而Action()方法是描述动物行为的,其行为方式是不确定的,需要视具体的动物而定,所以被修饰为abstract抽象的。
下面的程序是一个继承Animal类的描述“狗”的类,其程序代码为:
当抽象类中声明了抽象方法时,则在继承抽象类的子类中一定要覆盖抽象方法,并实现方法体的内容,例如上述程序在抽象类Animal中定义的Action()方法,其内容是在继承了Animal类的Dog类中实现的,因为Dog类是描述具体的“狗”对象,因此有其行为方式,抽象方法被覆盖后,其调用方式与普通方法一样。
抽象类描述的是事物所具有的共性,共同拥有的特征和行为,为其他需要继承的类提供一个基础类,当子类继承抽象类将共性完全继承时,还可以定义子类固有的与其他事物有别的特征和行为,例如在上述Dog程序中定义的wildness(野生)属性等。
3.2.2 final修饰符
Java语言体系出于安全性或面向对象设计上的考虑,有时希望一些类不能被继承,一些类、方法或变量不能被改变;或者一个类定义得非常完美,不需要再进行修改或扩展;或者该类、方法或变量对编译器和解释器的正常运行非常重要,不能轻易动态改变的;或者确保类、方法或变量的唯一性等,使用final修饰符可以达到上述目的。另外,final修饰符与abstract修饰符是不能同时使用的。
关键字final是用于类、方法或变量的修饰符。当final出现在类的声明中时,表示这个类不能有子类或被继承,是一个终态类;当final关键字出现在方法声明中时,表示该方法不能被覆盖,使用关键字static或private声明的方法隐含有final修饰功能;当final出现在变量的声明中时,表示该变量为常量,常量需要有初始化,即要被赋予一个固定的值,赋值操作可以在声明常量时进行,也可以在类的构造方法中进行。final修饰符的使用语法格式为:
例如,在Java的基础类库中,String(字符串)类就被声明为final型的,它保证了String数据类型的唯一性。
【示例3-16】 使用final修饰符修饰的类、方法和变量的Java演示程序。
因为当一个类被修饰为final时,它无法被任何类继承,继承“链”也就到了终点(节点),因此final类也被称为“叶子类”,在叶子类中定义的方法是属于叶子类的,自然也就成为final型的。因此,在叶子类中的方法被修饰为final型是没有意义的,但是,在其他非叶子类中定义final型方法是有意义的,即该方法在被继承的子类中是不能被覆盖的。