1.抽象类
抽象类和抽象方法的详细说明
1. 抽象类的基本概念
- 用
abstract修饰的类叫做抽象类 - 抽象类必须是父类(抽象类不能作为其他类的子类)
- 抽象类不能被实例化(不能创建对象)
- 抽象类可以有构造方法 (虽然不能实例化,但子类可以通过
super()调用)
java
abstract class Animal { // 抽象类声明
public Animal() { // 构造方法
System.out.println("Animal constructor");
}
}
2. 抽象方法的核心特性
- 用
abstract修饰的方法叫做抽象方法 - 抽象方法没有方法体(不包含具体实现)
- 抽象方法必须在抽象类中声明(普通类不能有抽象方法)
- 子类必须重写父类的所有抽象方法(除非子类也是抽象类)
java
abstract class Animal {
public abstract void eat(); // 抽象方法声明
}
3. 多态应用场景
抽象类虽然不能实例化,但可以通过父类引用指向子类对象的方式实现多态:
java
Animal myDog = new Dog(); // 多态:Animal引用指向Dog对象
myDog.eat(); // 实际调用Dog类的eat()方法
4. 使用限制和冲突
- 与final冲突 :
final类不能被继承 → 与abstract必须作为父类的特性冲突final方法不能被重写 → 与abstract方法必须被重写的特性冲突
- 与private冲突 :
private成员对子类不可见 → 无法实现抽象方法
- 与static冲突 :
static方法属于类而非实例 → 与需要子类实现的特性冲突
5. 实现要求
子类继承抽象类时:
- 必须实现所有抽象方法
- 若不实现,则子类也必须声明为
abstract - 通过
@Override注解明确表明重写关系
java
class Dog extends Animal {
@Override
public void eat() { // 必须实现抽象方法
System.out.println("Dog is eating");
}
}
6. 典型应用场景
-
框架设计 :定义通用行为规范
javaabstract class DatabaseConnector { public abstract void connect(); public abstract void disconnect(); } -
模板方法模式 :固定流程中的可变步骤
javaabstract class Game { abstract void initialize(); abstract void startPlay(); // 固定流程方法 public final void play() { initialize(); startPlay(); } }
2.接口
接口在Java中是一种完全抽象的类型定义,其核心特点主要体现在以下几个方面:
抽象方法的集合:
-
接口中的所有方法默认都是抽象方法(Java 8之前)
-
从Java 8开始,接口中可以包含默认方法(使用default修饰)和静态方法
-
示例:
javapublic interface Animal { void eat(); // 抽象方法 default void sleep() { // Java8默认方法 System.out.println("Sleeping..."); } }
实现规则:
-
Java类不能多继承,但可以实现多个接口
-
当一个类实现接口时,必须实现所有抽象方法(除非是抽象类)
-
示例:
javapublic class Dog implements Animal { @Override public void eat() { System.out.println("Dog is eating"); } }
成员限制:
-
接口中不能包含实例变量,但可以包含常量(public static final)
-
示例:
javapublic interface Constants { int MAX_VALUE = 100; // 默认为public static final }
构造与实例化:
-
接口没有构造方法,不能直接实例化
-
但可以通过多态方式使用:
javaAnimal myDog = new Dog();
接口继承:
-
接口可以继承多个其他接口
-
示例:
javapublic interface Pet extends Animal, Playable { void beFriendly(); }
实现要求:
- 非抽象类实现接口时,必须提供所有抽象方法的具体实现
- 如果实现多个接口且有相同方法签名,只需要实现一次
案例:
java
package com.qcby;
// 实现Comparable接口,指定泛型为Person
public class Person implements Comparable{
public Integer age;
public String name;
public Integer height;
public Person(String name, Integer age, Integer height) {
this.name = name;
this.age = age;
this.height = height;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
", height=" + height +
'}';
}
// 重写compareTo方法
@Override
public int compareTo(Object o) {//排序接口Comparable
//age - ((Person)o).age从小到大排序
//((Person)o).age - age从大到小排序
return age - ((Person)o).age;
}
}
java
package com.qcby;
public class ArraysDemo {
/**
* Object是所有类的父类 向上转型
* @param o
*/
public static void sort(Object[] o){
//将Object数组转换成Comparable数组
Comparable[] arr = (Comparable[]) o;
//这里能够实现强制类型转换是有一个前提的
//就是要排序的类必须实现Comparable接口
for(int i = 0; i < arr.length - 1; i++){
for(int j = 0; j < arr.length - 1 - i; j++){
//compareTo是 Comparable 接口中定义的核心方法
/**
* 若返回值 > 0:表示 arr[j] 大于 arr[j+1];
* 若返回值 = 0:表示两个元素相等;
* 若返回值 < 0:表示 arr[j] 小于 arr[j+1]。
*/
if(arr[j].compareTo(arr[j+1]) > 0){
Comparable temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
}
java
package com.qcby;
import java.util.Map;
import java.util.TreeMap;
public class Test {
public static void main(String[] args) {
Person p1 =new Person("小花",18,180);
Person p2 = new Person("小王",19,180);
Person p3 = new Person("小赵",20,170);
// Map<Person,Person> map = new TreeMap<>();
// map.put(p1,p1);
// map.put(p2,p2);
// map.put(p3,p3);
// System.out.println(map);
Person[] persons = new Person[]{p1,p2,p3};
ArraysDemo.sort(persons);
for (Person p:persons){
System.out.println(p);
}
}
}

3.接口和抽象类的异同:
抽象类是对类的一种抽象,本身是一种设计模板;接口是对行为的抽象是一种行为抽象
抽象是用来提取子类当中的共性代码 接口重点用于隐藏和封装
接口的方法默认是public,所有方法都是抽象方法,在接口中不能有方法的实现(Java 8开始接口方法可以有默认实现),抽象类可以有非抽象方法
一个类可以实现多个接口,但是最多只能继承一个抽象类
一个类实现接口的话要实现接口的所有方法,而抽象不一定(因为抽象类当中可以用非抽象的方法)