当前位置: 首页 > news >正文

【Java SE 】抽象类 和 接口 详解

 🔥博客主页🔥:【 坊钰_CSDN博客 】

欢迎各位点赞👍评论✍收藏⭐

目录

1. 抽象类

1.1 语法格式 

1.2 抽象类的特点

1.3 抽象类的优点

2. 接口

2.1 接口的概念

2.2 语法格式

2.3 接口的简单使用

2.4 接口的多态性

2.5 接口的特性

2.6 接口的继承

3. 利用接口实现自定义类型的比较

3.1 利用 Comparable 接口比较

3.2 利用 Comparator 接口建立比较器比较

4. Clone 接口

4.1 浅拷贝

4.2 深拷贝

5. 抽象类和接口的区别

​6. 小结


1. 抽象类

在 Java 编程中,所有的对象都是用类来描述的,但反过来想一想,不是所有的类都是用来描述对象的,我们把这一点统一出来,如果一个类没有足够的属性来描述对象,那这样的类我们就叫他抽象类,例如:

  • 语文、数学、英语,都继承 Lesson类,属于子类
  • Lesson类中虽然有 haveClass() 方法,但是却不知道具体上什么课,那这个类就是抽象的类
  • 通过下面三个子类继承Lesson类,重写 haveClass() 方法 ,可具体描述上的课程

1.1 语法格式 

Java 中描述抽象类用 abstract 关键字,被 abstract 修饰的类和方法称为抽象类和抽象方法

//被 abstract 修饰的类
public abstract class Lesson {//被 abstract 修饰的方法public abstract void haveClass();//抽象类可以有构造方法和普通方法public Lesson(){}public void ptintClass() {System.out.println("课程安排");}}
  • 抽象类也是类,可以含有普通方法和属性,构造方法也可以有

1.2 抽象类的特点

抽象类有很多特点需要去遵守,否则会报错 

  • 抽象类是不能实例化的,不能创建对象
  • 因为抽象类需要被继承,所以,抽象类不能被 private 修饰 
  • 抽象方法需要被重写,抽象方法不能被 static 和 final 修饰
  • 抽象方法必须被继承,必须用 abstract 修饰
  • 抽象类不一定有抽象方法,但有抽象方法的类一定是抽象类

1.3 抽象类的优点

 抽象类不能实例化,必须由子类重写抽象类中的方法,这样使其多了一重编译器的校验

2. 接口

2.1 接口的概念

在日常生活中,由很多接口的例子,如:手机充电器接口,电器插头,电脑USB接口

接口其实就是一种规则、标准,实现接口时,要遵守接口规则,就可以去使用接口

在 Java 编程中,接口可以看作为类的公共规则、规范,一种引用的数据类型

2.2 语法格式

接口既然是一种规则,那它的名字最好定义为形容词性的,如:可以跑的,可以飞的、可以潜水的......

接口的格式和定义类相似,只需把 class 关键字换为 interface 关键字就行了       

public interface I名称 {//方法可以有四种方式描述public abstract void fun1();public void fun2();abstract void fun3();void fun4();}
  • 接口一般命名前面最好加一个大写字母 I 
  • 接口中的方法全是抽象方法,就算没有被 abstract 修饰,也默认加上为抽象方法
  • 接口中没有普通方法和构造方法
  • 接口本质上也是抽象的,不能被继承只能被实现                                                  

 2.3 接口的简单使用

接口的使用用到 implements 关键字

public class 类名 implements 接口名 {//要实现接口中的抽象方法//.....}

子类和父类之间用 extends 关键字,而类和接口之间用 implements 关键字

interface IFlyable {  //接口//飞翔void fly();
}public class Brid implements IFlyable {  //实现接口private String bridName;public Brid(String bridName) {this.bridName = bridName;}//重写接口中抽象方法fly()public void fly() {System.out.println(bridName+" 在天上飞......");}public static void main(String[] args) {IFlyable iFlyable = new Brid("小鸟");iFlyable.fly();}}

2.4 接口的多态性

利用接口也可以实现多态性

父类 --- Animal 类

public class Animal {String name;int age;String color;public Animal(String name, int age, String color) {this.name = name;this.age = age;this.color = color;}
}

子类 --- Dog 类

public class Dog extends Animal implements IRun {public Dog(String name, int age, String color) {super(name, age, color);}public void run() {System.out.println(age+" 的 "+name+" 小狗在跑......");}}

子类 --- Brid 类

public class Brid extends Animal implements IRun,IFly {public Brid(String name, int age, String color) {super(name, age, color);}public void run() {System.out.println(age+" 的 "+name+" 小鸟在跑......");}public void fly() {System.out.println(age+" 的 "+name+" 小鸟在飞......");}}

测试类 --- Test类

public class Test {public static void testFly(IFly iFly) {iFly.fly();}public static void testRun(IRun iRun) {iRun.run();}public static void main(String[] args) {Brid brid = new Brid("小白",18,"蓝色")Dog dog = new Dog("小黑",28,"红色");testRun(dog);testRun(brid);testFly(brid);}}

可以看到,利用接口,不管对象是什么类,只要该对象的属性符合接口的要求和规则,就可以用直接使用接口,当传入不同对象时,接口的方法处理的产生不同的结果,这就是接口的多态性

2.5 接口的特性

接口和抽象类都有很多特性,来看看接口的特性

  • 接口本质上也是抽象的,不能用于实例化
  • 接口中的方法都是抽象方法,无构造方法
  • 接口中可以有属性,默认有 public static final 修饰
  • 接口中不能有静态的代码块 

2.6 接口的继承

在 Java 语法中,类与类之间不存在多继承,只能单继承,但是接口与接口之间可以进行多继承,使代码达到复用的目的

interface IFlyable {void fly();
}interface IRunable {void run();
}//继承后,又能飞,又能跑
interface Animals extends IFlyable,IRunable {}public class Duck implements Animals {@Overridepublic void fly() {}@Overridepublic void run() {}
}

3. 利用接口实现自定义类型的比较

当我们比较 5 和 10 时,很简单,整型数据一眼就看出来了,但是要比较我们的自定义类型呢?

3.1 利用 Comparable<T> 接口比较

利用 Comparable<T> 接口,规定分数的比较对象,用分数比较

import java.util.Arrays;class Student implements Comparable<Student>{public String name;public int age;public int score;public Student(String name, int age, int score) {this.name = name;this.age = age;this.score = score;}@Overridepublic int compareTo(Student o) {return this.score - o.score;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", score=" + score +'}';}
}public class Test {public static void bubble(Comparable[] comparables) {for (int i = 0; i < comparables.length - 1; i++) {for (int j = 0; j < comparables.length - 1 - i; j++) {if(comparables[j].compareTo(comparables[j+1]) > 0) {Comparable tmp = comparables[j];comparables[j] = comparables[j+1];comparables[j+1] = tmp;}}}}public static void main(String[] args) {Student student1 = new Student("zhangsan", 18,70);Student student2 = new Student("lisi", 19,55);Student student3 = new Student("wangwu", 20,96);Student student4 = new Student("songliu", 28,80);Student student5 = new Student("kongqi", 16,90);Student[] students = {student1, student2, student3, student4, student5};bubble(students);System.out.println(Arrays.toString(students));}}

3.2 利用 Comparator 接口建立比较器比较

利用 Comparator 接口建立比较器,更加灵活的比较

import java.util.Arrays;//用名字比较的比较器
class INameComparator implements Comparator<Student> {@Overridepublic int compare(Student o1, Student o2) {return o1.name.compareTo(o2.name);}
}//用年龄比较的比较器
class IAgeComparator implements Comparator<Student> {@Overridepublic int compare(Student o1, Student o2) {return o1.age - o2.age;}
}//用分数比较的比较器
class IScoreComparator implements Comparator<Student> {@Overridepublic int compare(Student o1, Student o2) {return o1.score - o2.score;}
}class Student {public String name;public int age;public int score;public Student(String name, int age, int score) {this.name = name;this.age = age;this.score = score;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", score=" + score +'}';}
}public class Test {public static void main(String[] args) {Student student1 = new Student("zhangsan", 18,70);Student student2 = new Student("lisi", 19,55);Student student3 = new Student("wangwu", 20,96);Student student4 = new Student("songliu", 28,80);Student student5 = new Student("kongqi", 16,90);Student[] students = {student1, student2, student3, student4, student5};IScoreComparator iScoreComparator = new IScoreComparator();IAgeComparator iAgeComparator = new IAgeComparator();INameComparator iNameComparator = new INameComparator();//用分数比较器比较Arrays.sort(students,iScoreComparator);System.out.println(Arrays.toString(students));System.out.println("=======================");//用年龄比较器比较Arrays.sort(students,iAgeComparator);System.out.println(Arrays.toString(students));System.out.println("=======================");//用名字比较器比较Arrays.sort(students,iNameComparator);System.out.println(Arrays.toString(students));}}

4. Clone 接口

Clone 接口,用于拷贝数据的,但是却分为深浅拷贝

4.1 浅拷贝

class Money {public float money = 25.6f;
}class People implements Cloneable {public String name;public Money m = new Money();public People(String name) {this.name = name;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}public class Test1 {public static void main(String[] args) throws CloneNotSupportedException {People people1 = new People("张三");People people2 =(People) people1.clone();//拷贝成功后,修改 people1 的值people1.m.money = 88.9f;//打印两个人的钱System.out.println(people1.m.money);System.out.println(people2.m.money);}
}

打印发现,两个人的钱都变了,这就是浅拷贝

原理图:

4.2 深拷贝

class Money implements Cloneable {public float money = 25.6f;@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}class People implements Cloneable {public String name;public Money m = new Money();public People(String name) {this.name = name;}//重写拷贝的代码,实现深拷贝@Overrideprotected Object clone() throws CloneNotSupportedException {People tmp = (People) super.clone();tmp.m = (Money) this.m.clone();return tmp;}
}public class Test1 {public static void main(String[] args) throws CloneNotSupportedException {People people1 = new People("张三");People people2 =(People) people1.clone();//拷贝成功后,修改 people1 的值people1.m.money = 88.9f;//打印两个人的钱System.out.println(people1.m.money);System.out.println(people2.m.money);}
}

原理图:

5. 抽象类和接口的区别

用一张图来展示

 6. 小结

以上就是对抽象类和接口的了解,具体还需宝子们去实践,如果觉得该博客对你有用的话,希望一键三连,点个关注不迷路,谢谢支持 !


http://www.mrgr.cn/news/56987.html

相关文章:

  • HTTP协议介绍
  • 《Effective C++》 笔记
  • 因为一句废话,大模型无法解决小学数学题?
  • 智慧产权,专业守护 —— 全影知产专利保护机构
  • 深入理解 RabbitMQ 及在.NET 中的应用
  • WSL2 Linux子系统调整存储位置
  • 高标准农田信息化推动农业产业链升级
  • Scala的内部类
  • uniapp学习(007-3 壁纸项目:系统高度等信息的操作)
  • 线程池常见面试题
  • hadoop
  • linux 编译安装的php7.4 开启pgsql,pdo_pgsql的扩展
  • 软件设计师考试大纲整理
  • JavaEE进阶----18.<Mybatis补充($和#的区别+数据库连接池)>
  • 如何设置Page Cache的大小为默认值
  • 32 类和对象 · 中
  • 卡牌抽卡机小程序,带来新鲜有趣的拆卡体验
  • 2025秋招八股文--mysql篇
  • 日志分析工具-应急响应实战笔记
  • 网络不稳定?试试这款Figma的中文替代设计工具
  • LLaMA Factory环境配置
  • ERP、SCM与CRM:三大系统的区别与整合策略
  • Go语言开发环境搭建
  • 源代码防泄密技术正在更新迭代中
  • curl请求接口的三个坑
  • 117.WEB渗透测试-信息收集-ARL(8)