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

14Java基础之抽象类、接口

抽象类

什么是抽象类?

  • 在Java中有一个关键字叫:abstract,它就是抽象的意思,可以用它修饰类、成员方法。
  • abstract如果修饰方法,那么该方法就是抽象方法,如果修饰类,那么该类就是抽象类。

抽象类的注意事项、特点

  • 抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。
  • 类该有的成员(成员变量、方法、构造器)抽象类都可以有。
  • 抽象类最主要的特点:抽象类不能使用new关键字来创建对象,它仅作为一种特殊的父类,让子类继承并实现。
  • 子类继承抽象类,那么就必须要重写完抽象类的全部抽象方法,否则该子类也要定义为抽象类。

案例:

父类:
public abstract class A {// 类该有的成员(成员变量、方法、构造器)抽象类都可以有。private String name;private int age;public A() {}public A(String name, int age) {this.name = name;this.age = age;}// 抽象方法:abstract修饰,只能有方法声明,没有方法体。public abstract void go();public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}子类:
// 一个类继承了抽象类,必须重写完抽象类的全部抽象方法,否则这个类也必须声明为抽象类。
public class B extends A{@Overridepublic void go() {}
}main方法:
// 目标:认识抽象类,搞清楚它的特点
public class Test {public static void main(String[] args) {// 抽象类的核心特点:不能被创建对象
//        A a = new A(); // 报错B b = new B();b.go();}
}

抽象类的场景与好处

  • 父类知道每个子类都要做某个行为,但每个子类要做的情况都不一样,父类就定义成抽象类方法,交给子类去重写实现,我们设计这样的抽象类,就是为了更好的支持多态。

案例:

父类:
public abstract class Animal {private String name;// 抽象类的好处:1. 方法体无意义时可以不写(简化代码)// 2. 强制子类重写方法(更好的支持了多态)public abstract void cry();public String getName() {return name;}public void setName(String name) {this.name = name;}
}子类:
public class Cat extends Animal {@Overridepublic void cry() {System.out.println("猫咪,喵喵喵的叫~");}
}public class Dog extends Animal{@Overridepublic void cry() {System.out.println("狗,汪汪汪的叫~");}
}测试:
//目标:搞清楚抽象类的应用场景
public class Test {public static void main(String[] args) {Animal a = new Cat();a.cry();Animal b = new Dog();b.cry();}
}
猫咪,喵喵喵的叫~
狗,汪汪汪的叫~

抽象类的常见应用场景:模板方法设计模式

模板方法设计模式解决了什么问题?

  • 解决方法中存在重复代码的问题。
    image

模板方法设计模式的写法

  1. 定义一个抽象类
  2. 在里面定义两个方法
  3. 一个是模板方法:把相同代码放到里面去。
  4. 一个是抽象方法:具体实现交给子类完成。
  • 建议使用final关键字来修饰模板方法,为什么?
    1. 模板方法是给对象直接使用的,不能被子类重写。
    2. 一旦子类重写了模板方法,模板方法就失效了。

案例:
目标:完成学生和老师写作文的功能
写作文的统一步骤:

  1. 第一步,写标题
  2. 第二步,写正文,但是内容各不相同
  3. 第三步,写结尾
抽象类:
public abstract class Person {// 把它设计成模板方法public final void writeArticle() {System.out.println("写标题");System.out.println("第一段内容相同");// 每个子类都是要写正文的,但是每个子类写的情况是不一样的,我们就可以把正文的书写定义成抽象方法// 具体的实现交给子类来写writeBoay();System.out.println("结尾是相同的");}public abstract void writeBoay();
}
子类:
public class Student extends Person{@Overridepublic void writeBoay() {System.out.println("我的正文是这样的...");}
}public class Teacher extends Person{@Overridepublic void writeBoay() {System.out.println("我的正文很优雅是这样的...");}
}测试方法:
public class Test {public static void main(String[] args) {Student s = new Student();s.writeArticle();Teacher t = new Teacher();t.writeArticle();}
}输出结果:
写标题
第一段内容相同
我的正文是这样的...
结尾是相同的
写标题
第一段内容相同
我的正文很优雅是这样的...
结尾是相同的
  • 注意:final关键字和abstract是互斥的。

接口

  • Java提供了一个关键字interface,用这个关键字我们可以定义出一个特殊的结构,接口。
    image

注意

  • 接口不能创建对象。接口是用来被类实现(implements)的,实现接口的类称为实现类
  • 这个实现可以理解为继承,继承接口类。
    image

案例:

接口类A:
// 接口
// 1.8版本之前,接口中只能定义常量和抽象方法
public interface A {// 1. 常量:接口中定义常量可以省略public static final,不写,默认会加上
//    public static final String SCHOOL_NAME = "霍格沃兹";String SCHOOL_NAME = "霍格沃兹";// 2. 抽象方法: 接口中定义抽象方法可以省略public abstract不写,默认会加上
//    public abstract void run();void run();void go();
}
接口类C:
public interface C {void eat();
}实现类:
// 实现类,相当于继承了接口的子类
// 实现类实现多个接口,必须重写完全部接口的全部抽象方法,否则这个类必须是抽象类。
public class BImpl implements A,C{@Overridepublic void run() {System.out.println("run");}@Overridepublic void go() {System.out.println("go");}@Overridepublic void eat() {System.out.println("eat");}
}测试:
//目标:认识接口,搞清楚接口的特点。
public class Test {public static void main(String[] args) {// 接口最需要注意的特点:不能创建对象
//        A a = new A(); // 报错:Cannot instantiate the type ABImpl b = new BImpl();b.run();b.go();b.eat();}
}

总结:

  1. 1.8版本之前,接口中只能定义常量和抽象方法
  2. 常量:接口中定义常量可以省略public static final,不写,默认会加上
  3. 抽象方法: 接口中定义抽象方法可以省略public abstract不写,默认会加上
  4. 接口最需要注意的特点:不能创建对象
  5. 实现类,相当于子类。实现类实现多个接口,必须重写完全部接口的全部抽象方法,否则这个类必须是抽象类。

接口的好处(重点)

  • 弥补了类单继承的不足,一个类同事可以实现多个接口。
  • 让程序可以面向接口编程,这样程序员就可以灵活方便的切换各种业务实现。(更利于程序的解耦合)

案例:

父类:
public class Person {}
子类:
public class Student extends Person implements Driver, Doctor{}
public class Teacher implements Driver, Doctor{}
接口:
public interface Driver {}
public interface Doctor {}
测试方法:
// 目标:理解接口的好处
public class Test {public static void main(String[] args) {// 1.弥补了类单继承的不足,接口让一个对象拥有更多角色,更多的能力。Person p = new Student();Driver d = new Student();Doctor doc = new Student();// 2.面向接口编程是软件开发中目前很流行的开发模式,能更灵活的实现解耦合。Driver d1 = new Teacher(); // 多态Doctor doc1 = new Teacher(); // 多态}
}注意:案例仅辅助理解接口的优势。

接口的应用案例:班级学生信息管理模块的开发

image

学生类:
public class Student {private String name;private char sex;private double score;public Student() {}public Student(String name, char sex, double score) {this.name = name;this.sex = sex;this.score = score;}public String getName() {return name;}public void setName(String name) {this.name = name;}public char getSex() {return sex;}public void setSex(char sex) {this.sex = sex;}public double getScore() {return score;}public void setScore(double score) {this.score = score;}
}
接口类:
public interface ClassData {void printAllStudentInfos();double getAverageScore();
}实现类1:
// 第一套实现类
public class ClassDataImpl1 implements ClassData{private ArrayList<Student> students;public ClassDataImpl1(ArrayList<Student> students) {this.students = students;}@Overridepublic void printAllStudentInfos() {System.out.println("展示所有学生信息:");for (int i = 0; i < students.size(); i++) {System.out.println("姓名:" + students.get(i).getName() +",性别:" + (students.get(i).getSex() == '男' ? "男" : "女") +",成绩:" + students.get(i).getScore());}}@Overridepublic double getAverageScore() {double sum = 0;System.out.println("展示所有学生的平均成绩");for (int i = 0; i < students.size(); i++) {sum += students.get(i).getScore();}return sum / students.size();}
}实现类2:
public class ClassDataImpl2 implements ClassData {private ArrayList<Student> students;public ClassDataImpl2(ArrayList<Student> students) {this.students = students;}@Overridepublic void printAllStudentInfos() {int count = 0;System.out.println("展示所有学生信息:");for (int i = 0; i < students.size(); i++) {System.out.println("姓名:" + students.get(i).getName() +",性别:" + (students.get(i).getSex() == '男' ? "男" : "女") +",成绩:" + students.get(i).getScore());if(students.get(i).getSex() =='男')count ++;}System.out.println("男生人数:" + count);System.out.println("女生人数:" + (students.size() - count));}@Overridepublic double getAverageScore() {double sum = 0;double min = students.get(0).getScore();double max = students.get(0).getScore();for (int i = 0; i < students.size(); i++) {sum += students.get(i).getScore();if(max < students.get(i).getScore())max = students.get(i).getScore();if(min > students.get(i).getScore())min = students.get(i).getScore();}System.out.println("最高成绩:" + max);System.out.println("最低成绩:" + min);System.out.println("展示所有学生的平均成绩");return (sum - max - min) / (students.size() - 2);}
}测试:
// 目标:实现班级学生管理系统
/*
* 1. 每个学生是一个对象,所以先定义学生类,用于创建学生对象,封装学生数据。
* 2. 定义接口:ClassData
* 3. 定义两套实现类,来分别处理,以便解耦合。
* */
public class Test {public static void main(String[] args) {ArrayList<Student> list = new ArrayList<>();list.add(new Student("张三", '男', 90));list.add(new Student("李四", '女', 80));list.add(new Student("王五", '男', 70));list.add(new Student("赵六", '女', 75));list.add(new Student("王二", '男', 85));// 多态:父类引用指向子类对象//ClassData data = new ClassDataImpl1(list);ClassData data = new ClassDataImpl2(list);data.printAllStudentInfos();System.out.println(data.getAverageScore());}
}

接口的多继承

  • 一个接口可以同时继承多个接口

接口多继承的作用

  • 便于实现类去实现。

案例:

// 目标:接口的多继承
public class Test {public static void main(String[] args) {// 类与类是单继承的,一个类只能直接继承一个父类// 类与接口是多实现的,一个类可以同时实现多个接口}
}
// 接口的多继承可以让实现类只实现一个接口,相当于实现了很多个接口
class D implements A{@Overridepublic void a() {System.out.println("a方法");}@Overridepublic void b() {System.out.println("b方法");}@Overridepublic void c() {System.out.println("c方法");}
}// 接口与接口是多继承的,一个接口可以同时继承多个接口
interface A extends B,C{void a();
}interface B{void b();
}interface C{void c();
}

总结:

  • 类与类是单继承的,一个类只能直接继承一个父类
  • 类与接口是多实现的,一个类可以同时实现多个接口
  • 接口与接口是多继承的,一个接口可以同时继承多个接口

JDK8开始,接口中新增了三种形式的方法

  1. 默认方法
  • 默认方法(也就是普通方法):必须用default修饰,它有方法体
  • 默认会用public修饰
  • 必须用接口的实现类的对象来调用
  1. 私有方法
  • 私有方法(私有的实例方法),JDK9开始有的
  • 只能在当前接口内部的默认方法或者私有方法中调用

3.静态方法

  • 默认会用public修饰
  • 接口的静态方法,必须用接口名本身调用

JDK8开始为什么要新增这三种方法?

  • 增强了接口的能力,更便于项目的拓展和维护。

** 接口使用的注意事项**

  1. 一个接口继承多个接口,如果多个接口中存在方法签名冲突。则此时不支持多继承。
  2. 一个类实现多个接口,如果多个接口中存在方法签名冲突,则此时不支持多实现。
  3. 一个类继承了父类,又同时实现了接口,父类中和接口中有同名的默认方法,实现类会优先用父类的。
  4. 一个类实现了多个接口,多个接口中存在同名的默认方法,可以不冲突,这个类重写该方法即可。
    案例:
public class Test {public static void main(String[] args) {
//        Cat c = new Cat();
//        c.run();
//        c.test();}
}// 1. 一个接口继承多个接口,如果多个接口中存在方法签名冲突。则此时不支持多继承。
/*
interface A1{String run();
}
interface B1{void run();
}
interface C1 extends A1,B1{}
*/
// 2. 一个类实现多个接口,如果多个接口中存在方法签名冲突,则此时不支持多实现。
/*
interface A2{String run();
}
interface B2{void run();
}
class C2 implements A2,B2{}
*/
// 3. 一个类继承了父类,又同时实现了接口,父类中和接口中有同名的默认方法,实现类会优先用父类的。
/*
class Animal{public void run(){System.out.println("动物跑的贼快~");}
}
interface Go{default void run(){System.out.println("跑的贼快~");}
}
class Cat extends Animal implements Go{public void test(){run();Go.super.run();// 这种方式会调用接口的默认方法}
}
*/
// 4. 一个类实现了多个接口,多个接口中存在同名的默认方法,可以不冲突,这个类重写该方法即可。
interface A3{default void run(){System.out.println("A3 run");}
}
interface B3{default void run(){System.out.println("B3 run");}
}
class C3 implements A3,B3{@Overridepublic void run() {//A3.super.run();//B3.super.run();System.out.println("C3 run");}
}
http://www.wooajung.com/news/35400.html

相关文章:

  • 深入解析:mac电脑安装 nvm 报错如何解决
  • 洛谷 P12078 [OOI 2025] Best Runner 题解
  • 远程git ssh配置1
  • 7月24日总结
  • VIRTUBOX BUG
  • 精通Python PDF裁剪:从入门到专业的三重境界
  • 如何在群晖虚拟机快速部署线上web网站并实现公网访问
  • 向他人分享我的音频
  • - BigBosscyb - 博客园
  • 整体二分
  • 闲来无事
  • - daydreamer_zcxnb - 博客园
  • - Redamancy_Lydic - 博客园
  • - darling331 - 博客园
  • - kintsgi - 博客园
  • TIM外部中断
  • LPC总线设计及其仿真验证
  • Fluent许可证类型
  • 多值依赖
  • Windows 验证耳机输入是否正常
  • ABC典题总结
  • springboot项目解决报错:spring boot application in default package
  • LaTeX中为何推荐substack而不使用\atop?
  • 手机网页版浏览器seo案例分析及解析
  • 知名品牌vi设计宁波优化推广找哪家
  • 做国际贸易的网站沧州网站推广优化
  • 网站框架都有什么用重庆网站快速排名提升
  • 凡科自助建站靠谱吗网站安全检测在线
  • 哪些国家网站无须备案企业所得税优惠政策
  • 泰安房产网信息网官网seo服务 收费