13. final关键字
final的意思是“最终的”。在java中,可以使用final关键字声明类、属性、方法,要注意以下几点:
- 使用final修饰的类不能有子类,不可被继承。
- 使用final修饰的方法不能被子类重写。
- 使用final修饰的变量(成员变量和局部变量)是常量,不可被重新赋值。
13.1 final修饰类
java中类被final修饰后,该类无法被继承,也不能派生出子类。
// final修饰类
public final class Animal {
}
// 继承
class Dog extends Animal {
//报错 java: 无法从最终Animal进行继承
}
// 测试类
class DogTest {
public static void main(String[] args) {
Dog dog = new Dog();
}
}
上面的代码,编译过程中报错: java: 无法从最终Animal进行继承, 说明final修饰的类无法继承。
13.2 final修饰方法
当使用final修饰方法时,子类无法重写此方法。
// Animal父类
public class Animal {
public final void shout() {
}
}
// Dog子类
class Dog extends Animal {
// 重写Animal类的shout()方法
public void shout() {
// 报错: java: Dog中的shout()无法覆盖Animal中的shout()
}
}
// 测试类
class DogTest {
public static void main(String[] args) {
Dog dog = new Dog();
}
}
上面的代码,编译过程中报错: java: Dog中的shout()无法覆盖Animal中的shout(), 被覆盖的方法为final。
13.3 final修饰变量
在java中,使用final修饰的变量是常量,只能在定义时被赋值一次,在程序无法修改常量的值。
// 局部常量
public class DogTest {
public static void main(String[] args) {
final int AGE = 20;
AGE = 18; // 报错,不能重新赋值给常量
}
}
// 全局常量
class Dog {
// 全局常量
public static final String NAME = "哈士奇";
public static void main(String[] args) {
// 局部常量
final int AGE = 20;
final String NAME = "雪纳瑞";
System.out.println(AGE); // 20
System.out.println(NAME); // 雪纳瑞
System.out.println(Dog.NAME); // 哈士奇
}
}
14. 抽象类和接口
14.1 抽象类
在java中定义一个类时,要定义方法和属性,但有时候方法的实现是无法确定的。如定义Animal类时,shout()方法用于描述动物的叫声,但不同的动物有不同的叫声,因此在shout()方法中无法准确的描述动物的叫声。
针对上面的情况,java通过抽象方法来满足这种需求。
抽象方法是使用 abstract 修饰的成员方法,定义抽象方法时不需要实现方法体。语法如下:
abstract 返回值类型 方法名称 (形参列表);
当一个抽象方法存在某个类中,当前的类必须是抽象类,抽象类也是使用abstract进行的类。语法如下:
abstract class 类名{
属性;
访问权限 返回值类型 方法名称(形参列表){ // 普遍方法
return [返回值];
}
访问权限 返回值类型 方法名称(形参列表); // 抽象方法
}
从上面的语法可以发现,抽象类定义比普通类多了一些抽象方法,其它地方与普通类基本上相同。
抽象类定义的规则如下:
- 包含抽象方法的类必须是抽象类。
- 抽象方法和抽象类都必须使用abstract声明。
- 抽象方法只需定义不需要实现。
- 如果一个非抽象类继承了抽象类,那么子类必须实现父类中定义的全部抽象方法。
- 抽象方法不能使用private修饰,因为抽象方法要在子类中被实现。
// Animal父类
public abstract class Animal {
// 抽象方法shout
abstract void shout();
}
// Dog子类
public class Dog extends Animal {
// 实现Animal类的抽象shout方法
public void shout() {
System.out.println("汪汪汪...");
}
}
public class Cat extends Animal {
@Override
public void shout() {
System.out.println("喵喵喵...");
}
}
// 测试类
public class AnimalTest {
public static void main(String[] args) {
Dog dog = new Dog();
dog.shout(); // 汪汪汪....
Cat cat = new Cat();
cat.shout(); // 喵喵喵....
}
}
练习1: 定义一个抽象类Shape,有抽象方法abstract double area();用于计算面积
有普通方法 void printDescription()输出:This is a shape.
定义一个Circle 类继承Shape类,有私有化属性double radius,常量属性PI=3.14,
对Circle类进行封装,重写area方法,
定义测试类,声明Circle对象,对area方法测试。
package task;
// 抽象类
public abstract class Shape {
// 计算面积的方法
public abstract double area();
// 描述图形的信息
public void printDescription() {
System.out.println("This is a shape.");
}
}
package task;
// 子类Circle
public class Circle extends Shape {
public static final double PI = 3.14; // 圆周率
private double radius; // 半径
public Circle() {
}
public Circle(double radius) {
setRadius(radius);
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
if (radius < 0) {
System.out.println("圆的半径不能是负数!");
radius = 0;
}
this.radius = radius;
}
// 实现父类中的抽象方法area
public double area() {
return PI * getRadius() * getRadius();
}
// 重写方法printDescription
public