目录
🌏1. 理解接口的概念
🌎2. 学会接口的语法(关键字implements)
🌍3. 掌握接口的用法
🌏4. 明白接口的特性
🌏5. 教你如何实现多个接口
🌎6. 接口之间是怎么继承的
🌏7. 给接口举个例子
🗺️7.1 Comparable接口
🗺️7.2 比较器Comparator
🌍8. Clonable接口和深拷贝
🗺️8.1 Clonable接口
🗺️8.2 浅拷贝
🗺️8.3 深拷贝
🌎9. 接口和抽象类的区别
🌏1. 理解接口的概念
接口就是公共的规范标准,如果要使用就要遵守这个标准,而在Java中,接口可以看成是:一种特殊的类,它的规范标准就是,里面全部都是由全局常量和公共的抽象方法组成,并且它是解决java无法使用多继承的一种手段,所以如果要使用就要遵守这个标准
🌎2. 学会接口的语法(关键字implements)
🟩使用interface来修饰接口
注意:
(1)创建接口时,接口的命名一般以大写字母 I 开头
(2)建议接口中的方法和属性不要加任何修饰符号, 保持代码的简洁性
🌍3. 掌握接口的用法
🟥接口是不能直接使用的,必须要有一个类来实现该接口,实现接口中的所有抽象方法
格式就是这样
class 类名称 implements 接口名称{
//
}
🌏4. 明白接口的特性
🤠(1)接口当中的成员变量,默认都是 public static final 修饰的
🤠(2) 接口中的成员方法,默认都是抽象方法
也就是public abstract 修饰的
🤠(3)接口中的普通成员方法,是不能有具体的实现的
这里就报错了
🤠(4)接口中的普通成员方法,如果要有具体实现,就必须加上default【从JDK8开始】
🤠(5) 接口中可以有静态的成员方法,
但是不管是静态方法还是default方法都是public修饰的
🤠(6)接口本身也是不可以进行实例化的
🤠(7) 类和接口的关系是使用 implements 来关联的
🤠(8)一个接口可以引用,具体实现类的,向上转型
🤠 (9)接口中不能有静态代码块,实例代码块,构造方法
🤠(10)一个抽象类实现一个接口,可以不重写这个抽象方法,但是这个类一旦被使用,就也要重写构造方法
🌏5. 教你如何实现多个接口
java中是不支持多继承的,一个类只能有一个父类,那么如何实现多个类的使用
这就要用到接口了
一个类可以实现多个接口。
下面看例子
这个是个抽象类动物
abstract class Animal {
public String name;
public int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public abstract void eat() ;
}
然后再看两个接口
interface IRunning {
public void run() ;
}
interface IFlying {
public void fly();
}
下面创建一个动物 狗
⚜️如何使用接口呢,很简单,直接在子类继承父类的后面 加关键字 然后连接接口就可以了
class Dog extends Animal implements IRunning{
public Dog(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println(name + "正在吃狗粮! ");
}
@Override
public void run(){
System.out.println(name+" 正在跑 ");
}
}
再创建一个动物 鸟
这里注意,在创建鸟时使用了两个接口 关键字implements后面 跟两个接口,中间用逗号连接
并且还要注意的是,一个类在实现多个接口的时候,每个接口中的抽象方法都要实现,否则类必须设置成抽象类
class Bird extends Animal implements IRunning,IFlying{
public Bird(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println(name + "正在吃鸟粮! ");
}
@Override
public void run(){
System.out.println(name+" 正在慢跑走 ");
}
@Override
public void fly(){
System.out.println(name+" 正在用翅膀飞 ");
}
}
上面的这个例子,说明了java中 ,
一个类继承一个父类,同时实现多种接口
而接口表达的作用是,具有___功能或特性
🌎6. 接口之间是怎么继承的
类和类之间是单继承的,一个类可以有多个接口,接口和接口之间是可以多继承的。
也就是,用接口就可以实现多继承。
下面看代码,例子
interface IA {
void funcA();
}
interface IB{
void funcB();
}
//扩展功能--接口的继承
interface IC extends IA,IB{
void funC();
}
class T implements IC {
@Override
public void funcA() {
}
@Override
public void funcB() {
}
@Override
public void funC() {
}
}
这个例子中,为了实现接口的继承,
使用了extends关键字,在关键字后面跟两接口,中间用逗号连接
接口之间的继承相当于把多个接口合并在一起,也就是扩展功能
🌏7. 给接口举个例子
🗺️7.1 Comparable接口
🤠比较自定义类型的大小接口Comparable<>
如果是自定义类型数据,需要比较大小,那就要先明确根据什么去比较大小,
这里也可以简化一下代码
@Override
public int compareTo(Student o) {
return this.age - o.age;
}
这里的this就是student,o就是student1,这两个根据age比较大小
public static void main(String[] args) {
Student student = new Student("zhang san",20,60);
Student student1 = new Student("li si",21,70);
Student student2 = new Student("wang wu",21,80);
if(student.compareTo(student1) > 0){
System.out.println("student > student1");
}else if (student.compareTo(student1) == 0){
System.out.println("student == student1");
}else {
System.out.println("student < student1");
}
}
public static void main(String[] args) {
Student[] students = new Student[3];
students[0] = new Student("zhang san",22,60);
students[1] = new Student("li si",21,70);
students[2] = new Student("wang wu",21,80);
System.out.println("排序前" + Arrays.toString(students));
Arrays.sort(students);
System.out.println("排序后" + Arrays.toString(students));
}
⚜️如果以后是自定义类型的数据,牵扯到大小比较,需要进行一些设计的。比如实现接口
🗺️7.2 比较器Comparator
🤠比较器Comparator
比较器Comparator比前面的Comparable<>更加灵活,
因为Comparable比较是写的固定的,而Comparatir可以根据用户的需求去指定选择根据什么样的方式进行比较,
比如说比较年龄
class AgeComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.age - o2.age;
}
}
比如说比较分数
class AgeComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.age - o2.age;
}
}
需要比较什么就选择什么,非常的灵活
public static void main(String[] args) {
Student student = new Student("zhang san",20,60);
Student student1 = new Student("li si",21,70);
AgeComparator ageComparator =new AgeComparator();
int ret = ageComparator.compare(student,student1);
System.out.println(ret);
ScoreComparator scoreComparator = new ScoreComparator();
int ret2 = scoreComparator.compare(student,student1);
System.out.println("分数比较" + ret2);
}
⚜️当然两个也是可以共存的
compareTo是根据学生对象去调用的,而Comparator是根据对应选择比较来调用的
⚜️前面比较的都是数字,那么Compartor是如何来比较字符串的
下面来进行name的比较
注意看name是String类型,String实现了Comparable接口
所以它默认有Comparable方法那就可以直接这样做了
class NameComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.name.compareTo(o2.name);
}
}
我们也可以自己写一个sort方法来实现排序过程,使用冒泡排序
public static void sort(Comparable[] array) {
for (int i = 0; i < array.length - 1; i++) {
for (int j = array.length - 1 - i; j > i; j--) {
if (array[j].compareTo(array[j+1]) > 0) {
// 顺序不符合要求, 交换两个变量的位置
Comparable tmp = array[j - 1];
array[j - 1] = array[j];
array[j] = tmp;
}
}
}
}
🌍8. Clonable接口和深拷贝
🗺️8.1 Clonable接口
这是一个空接口(标记接口),没有抽象方法,也就是类可以被克隆
Cloeable表示person这个类可以被克隆
但是如果要克隆那就必须要重写clone这个方法
可以看到调用的是Object这个cloen方法
可以简单的看一下克隆过程
class person implements Cloneable{
public int age = 11;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "person{" +
"age=" + age +
'}';
}
}
public class Test01 {
public static void main(String[] args) throws CloneNotSupportedException {
person person = new person();
person person1 = (person) person.clone();
}
}
🤠所以,Object 类中存在一个 clone 方法, 调用这个方法可以创建一个对象的 "拷贝".
但是要想合法调用 clone 方法, 必须要 先实现 Clonable 接口,
🗺️8.2 浅拷贝
下面看这样的一段代码
class Money {
public double money = 19.9;
}
class person implements Cloneable{
public int age = 10;
public Money m = new Money();
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "person{" +
"age=" + age +
'}';
}
}
public class Test01 {
public static void main(String[] args) throws CloneNotSupportedException {
person person = new person();
person person1 = (person) person.clone();
System.out.println(person.m.money);
System.out.println(person1.m.money);
}
}
它会输出什么
如果此时修改
person1.m.money = 99;
那么输出会不会变化呢,要明白这个问题,就要先搞清楚这段代码的存储方式
都是指向同一个money的所以,修改一个,另一个也会变化,这样的存储方法就叫做浅拷贝
🗺️8.3 深拷贝
但是最后指向的都是
所以修改一个另一个也会被改变,这个也就是浅拷贝
所以深拷贝就是希望,最后指向的不是一块空间,修改一个另一个不会被改变
深拷贝就是希望实现这样的一个效果,
下面修改一下试试看
person1.m.money = 99;
和我们希望的一样,修改后不影响另一个值
🌎9. 接口和抽象类的区别
区别 | 抽象类 | 接口 |
---|---|---|
成员变量 | 普通类一样 | 默认被public static final修饰 |
成员方法 | 构造方法或普通方法 | 抽象方法,静态方法,default默认方法 |
子类使用 | 用extends关键字继承抽象类 | 用implements关键字实现接口 |
子类限制 | 一个子类继承一个抽象类 | 一个子类实现多个接口 |
关系 | 一个抽象类可以实现若干接口 |
接口不能继承抽象类,但接口可以使用 extends关键字继承多个父接口 |
权限 | 和普通类一样 | public |