新数据结构(10)——Java抽象类和接口
抽象类
抽象类产生原因
子类可以重写父类中的方法并覆盖父类中的变量
抽象类会将子类里共有的代码逻辑进行提取和抽象化
抽象类通常被设计作为父类来实现代码复用
抽象类的特点
抽象类只需要做方法的定义,不需要实现
一个被abstract修饰的类被称为抽象类,一个由abstract修饰的方法则被称为抽象方法。
由abstract修饰的抽象方法,通常不在抽象类本身中实现,而是作为必须由子类覆盖和实现的方法的定义存在。
只有抽象类中才能包含抽象方法,而普通类中则不能声明或包含抽象方法。
在抽象类中,并非所有的方法都必须是抽象方法,它也可以包含普通方法,而这些普通方法则不需要被子类重写。
抽象类不能被实例化,原因在于其设计初衷是为了被其他类继承,并且它们通常没有提供用于创建实例的具体构造器。
final
关键字和abstract
关键字不能同时应用于同一个类或者同一个方法上:当final
关键字作用于类上时,意味着该类不能被其他类继承;而当final
关键字作用于方法上时,则表示该方法不能被其子类重写。相反地,abstract
关键字则用于声明抽象类或抽象方法,它们的目的正是为了被继承或重写。
抽象方法不能被声明为static
,因为static
关键字是针对类层次结构的,它表示方法是属于类本身而不是类的实例(对象)。而抽象方法则是针对对象层次的,它们需要在子类中通过实例被具体实现。因此,从逻辑上讲,static
和abstract
不能一起使用于同一个方法上,因为它们的概念是相互排斥的。
当一个子类继承了一个抽象类之后,如果该子类不打算实现从抽象类继承来的所有抽象方法,那么这个子类本身也必须被声明为抽象类。
一个被声明为抽象类的类,在类的继承关系中,一定是作为其他类的父类或祖先类存在。
接口
接口产生原因
在Java编程语言中,一个子类只能继承自一个直接的父类(这被称为Java的单继承机制),但一个子类可以同时实现多个接口
接口的特征
接口interface
是通过implements
关键字由类来实现的,一个类通过使用implements
关键字来声明它实现了某个接口。
在接口中声明的所有成员变量,默认都是由public
、static
和final
这三个关键字修饰的,即它们都是公开的、静态的、且不可变的常量。
在接口中声明的所有方法,如果不显式指定其访问修饰符和抽象性,那么它们默认都是由public
和abstract
这两个关键字修饰的,即它们都是公开的抽象方法。
在接口的定义中,是不包含构造器的,因此接口本身不能被直接实例化以创建对象。
接口中定义的所有方法均为抽象方法,这与抽象类不同,因为抽象类除了可以包含抽象方法外,还可以包含已经实现的具体方法。
一个接口可以继承自另一个或多个接口(这种继承的本质在于实现代码的复用和功能的扩展),从而允许接口之间共享方法和常量定义。
接口是对一系列方法的抽象声明,而实现了该接口的子类(或称为实现类)则必须提供这些抽象方法的具体实现。这里需要注意的是,虽然接口本身不直接作为父类,但它定义了子类必须遵循的契约,即实现接口中声明的所有抽象方法。
对对象进行排序
无法直接使用Arrays.sort()进行排序,需要使用接口
在 Java 中,Arrays.sort()
方法默认只能对基本数据类型(如 int
、double
等)或实现了 Comparable
接口的对象数组进行排序。对于自定义类(如 Person
),Arrays.sort()
无法直接对其进行排序,因为 Arrays.sort()
不知道如何比较两个 Person
对象的大小。因此,为了使 Person
对象能够被排序,需要让 Person
类实现 Comparable
接口,并重写 compareTo()
方法,明确指定对象之间的比较规则。这段代码通过实现 Comparable
接口并重写 compareTo()
方法,为 Person
类定义了排序规则,使得 Arrays.sort()
能够对 Person
对象数组进行排序。
例子:
package Test20250217;
import java.util.Arrays;
public class TestSort {
public static void main(String[] args) {
Person p1 = new Person("小黑",18,189.5);
Person p2 = new Person("小白",22,185.3);
Person p3 = new Person("小虎",20,184.5);
Person p4 = new Person("小何",24,185.1);
Person p5 = new Person("小阿",21,181.5);
//学过八大排序
Person[] arrPersons = new Person[]{p1,p2,p3,p4,p5};
//实现Comparable接口
Arrays.sort(arrPersons);
System.out.println(Arrays.toString(arrPersons));
}
}
package Test20250217;
import java.util.Comparator;
public class Person implements Comparable<Person> {
public String name;
public int age;
public double height;
public Person(String name,int age,double height){
this.name = name;
this.age = age;
this.height = height;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", height=" + height +
'}';
}
@Override
// public int compareTo(Person o) {
// //指定 age 进行从小到大排序 return age - o.age;
// //指定 age 进行从大到小排序 return o.age - age;
// return (int) (height - o.height);
// }
public int compareTo(Person o) {
// return o.age - age;
return (int) (height - o.height);
}
}
重写Arrays.sort使之快速排序
package Test20250217;
import java.util.Arrays;
public class TestSort {
public static void main(String[] args) {
Person p1 = new Person("小黑",18,189.5);
Person p2 = new Person("小白",22,185.3);
Person p3 = new Person("小虎",20,184.5);
Person p4 = new Person("小何",24,185.1);
Person p5 = new Person("小阿",21,181.5);
//学过八大排序
Person[] arrPersons = new Person[]{p1,p2,p3,p4,p5};
//实现Comparable接口
Arrays2.sort(arrPersons);
System.out.println(Arrays.toString(arrPersons));
}
}
package Test20250217;
public class Arrays2 {
public static void sort(Comparable[] o){
sort(o,0,o.length-1);
}
public static void sort(Comparable[] arr,int left,int right){
if(left>right){
return;
}
int i=left;
int j=right;
Comparable base=arr[left];
while(i!=j){
while(arr[j].compareTo(base) >=0&&i<j){
j--;
}
while(arr[i].compareTo(base)<=0&&i<j){
i++;
}
Comparable temp=arr[j];
arr[j]=arr[i];
arr[i]=temp;
}
arr[left]=arr[i];
arr[i]=base;
sort(arr,left,i-1);
sort(arr,i+1,right);
}
}