抽象(abstract)
java关键字abstract,可用于修饰类、方法。
抽象类
格式:修饰符 abstract class 类名{}
1、此类不能实例化
2、抽象类中一定有构造器,便于子类实例化时调用
3、开发中,都会提供抽象类的子类,让子类对象实例化,完成相关的操作
抽象方法
格式:修饰符 abstract 返回值 方法名(){}
1、抽象方法只能声明方法,没有方法体
2、包含抽象方法的类一定声明为抽象类
3、若子类重写了父类中的所有的抽象方法后,此子类方可实例化
特点:
- 抽象类中可以没有抽象方法
- 类中可以定义抽象方法
- 抽象类不能直接实例化,要通过其普通的子类实例化,抽象类可以创建构造方法,为子类调用
- 子类继承抽象类必须实现抽象类中所有抽象方法,否则子类也必须声明为抽象类
- 抽象类修饰符必须是public或友好的(即默认的),不能是private,若为私有的子类无法继承重写抽象方法
示例一:
/**
* abstract关键字的使用<br>
* abstract可以用来修饰的结构有:类、方法<br>
*
* @author jb
* @date 2022/08/08
*/
public class AbstractTest {
public static void main(String[] args) {
// 抽象类不能实例化
// Person2 p = new Person2();
// p.eat();
Person2 s = new Student("张三", 18); // 子类实例化对象,向上转型
System.out.println(s); // com.bingeone.test.Student@70dea4e
System.out.println(s.name); // 张三
s.sing(); // 调用Student类的方法
s.eat();// 调用Person2类的方法
s.breath();
}
}
abstract class Creature {
public abstract void breath();
}
abstract class Person2 extends Creature { // Person2类继承Creature类,此时有两个抽象方法
String name;
int age;
Person2() {
}
Person2(String name, int age) {
this.name = name;
this.age = age;
}
public void eat() {
System.out.println("人要吃饭!");
}
public void walk() {
System.out.println("人可以走路!");
}
// 抽象方法,没有方法体
public abstract void sing();
}
class Student extends Person2 {
public Student(String name, int age) {// 此继承父类,借鉴name,age的属性名,在子类中可以访问
super(name, age);
}
@Override
public void sing() {
System.out.println("student is singing");
}
@Override
public void breath() {
System.out.println("student is breathing");
}
}
示例二:
public abstract class Vehicle{
public abstract double calcFuelEfficiency(); // 计算燃料效率的抽象方法
public abstract double calcTripDistance(); // 计算行驶距离的抽象方法
}
public class Truck extends Vehicle{
public double calcFuelEfficiency(){
//编写计算卡车的燃料效率具体方法
}
public double calcTripDistance(){
//编写计算卡车行驶距离的具体方法
}
}
示例三:
abstract class GeometricObject{
public abstract double findrea();
}
class Circle extends GeometricObject{
private double radius;
public double findrea(){
return 3.14*radius*radius;
}
}
注意事项:
- abstract不能用来修饰:属性,构造器等
- abstract不能用来修饰私有方法、静态方法、final的方法、final的类
抽象类的匿名子类使用方式:
/**
* 抽象类的匿名子类使用方法
*
* @author jb
* @date 2022/08/08
*/
public class PersonTest2 {
public static void main(String[] args) {
// 1、创建匿名子类的非匿名对象
Person3 p = new Person3() {
@Override
public void eat() {
System.out.println("吃什么呢。。。");
}
@Override
public void breath() {
System.out.println("有氧呼吸。。。");
}
};
method(p);
System.out.println("***********");
// 2、创建匿名子类的匿名对象 -> 抽象类的简化用法
method(new Person3() {
@Override
public void eat() {
System.out.println("好好吃饭");
}
@Override
public void breath() {
System.out.println("深呼吸。。。");
}
});
System.out.println("***********");
// 3、匿名对象 -> 创建普通类作为实参传给方法使用
method(new Employee("李四", 180));
System.out.println("***********");
// 4、正常使用方式:非匿名对象
Employee employee = new Employee("张三", 185);
employee.eat();
employee.breath();
System.out.println(employee);
}
public static void method(Person3 p) {
p.eat();
p.breath();
}
}
/**
* 抽象类Person3
*/
abstract class Person3 {
public abstract void eat();
public abstract void breath();
}
/**
* 继承抽象类的子类Employee
*/
class Employee extends Person3 {
String name;
int height;
@Override
public void eat() {
System.out.println(name + "正在吃饭。。");
}
@Override
public void breath() {
System.out.println(name + "有氧呼吸运动");
}
public Employee(String name, int height) {
super();
this.name = name;
this.height = height;
}
@Override
public String toString() {
return "Employee [name=" + name + ", height=" + height + "]";
}
}
//结果:
吃什么呢。。。
有氧呼吸。。。
***********
好好吃饭
深呼吸。。。
***********
李四正在吃饭。。
李四有氧呼吸运动
***********
张三正在吃饭。。
张三有氧呼吸运动
Employee [name=张三, height=185]
抽象类的应用
模板方法:在软件开发中实现一个算法,整体步骤很固定、通用,这些步骤已经在父类中写好了。但是某些部分易变、将此部分抽象出来,供子类实现。这就是模板模式
示例四:
/**
* 抽象类的应用:模板方法的设计模式<br>
*
* @author jb
* @date 2022/08/07
*/
public class TemplateTest {
public static void main(String[] args) {
SubTemplate t = new SubTemplate();
t.spendTime(); // 调用父类的方法
}
}
abstract class Template {
public void spendTime() {
long start = System.currentTimeMillis();
this.code(); // 不确定部分,易变部分
long end = System.currentTimeMillis();
System.out.println("花费的时间为: " + (end - start) + "秒");
}
public abstract void code();
}
class SubTemplate extends Template {
@Override
public void code() {
for (int i = 2; i < 100; i++) {
boolean isFlag = true;
for (int j = 2; j <= Math.sqrt(i); j++) {
if (i % j == 0) {
isFlag = false;
break;
}
}
if (isFlag) {
System.out.println(i);
}
}
}
}
应用场景:
模板方法设计模式是编程中经常使用的模式,各个框架、类库中都有它的影子
- 数据库访问的封装
- Junit单元测试
- JavaWeb的Servlet中关于doGet/doPost的方法调用
- Hibernate中模板程序
- Spring中JDBCTemplate、HibernateTemplate等