Java面向对象之接口和抽象类的区别一目了然

2024-02-28 19:12

本文主要是介绍Java面向对象之接口和抽象类的区别一目了然,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

image

介绍

相信对于Java面向对象部分,很多人很长一段时间对于接口和抽象类的区别,使用场景都不是很熟悉,同是作为抽象层重要的对象,工作中到底什么情况下使用抽象类,不是很清楚。本文就一次性把这些概念一次性说清楚,不用再烦恼了,哈哈!

核心概念

  1. 接口与抽象类最明显的区别可能就是使用上的惯用方式。接口的典型使用是代表一个类的类型或一个形容词,如 Runnable 或 Serializable,而抽象类通常是类层次结构的一部分或一件事物的类型,如 String 或 ActionHero。

  2. java8开始增加默认方法的极具说服力的理由是它允许在不破坏已使用接口的代码的情况下,在接口中增加新的方法。默认方法有时也被称为守卫方法或虚拟扩展方法。

  3. 抽象类仍然是一个类,在创建新类时只能继承它一个。而创建类的过程中可以实现多个接口。

  4. 有一条实际经验:尽可能地使用接口而不是抽象类。只有当必要时才使用抽象类。除非必须使用,否则不要用接口和抽象类。大多数时候,普通类已经做得很好,如果不行的话,再移动到接口或抽象类中。

  5. 任何抽象性都应该是由真正的需求驱动的。当有必要时才应该使用接口进行重构,而不是到处添加额外的间接层,从而带来额外的复杂性。恰当的原则是优先使用类而不是接口。从类开始,如果使用接口的必要性变得很明确,那么就重构。接口是一个伟大的工具,但它们容易被滥用。

接口和抽象类的区别

接口和抽象类都是Java中定义行为的方式,但它们之间存在一些重要的区别。

image

  1. 定义与实现

接口:接口是一种完全抽象的类型,它只包含抽象方法和常量。接口不能被实例化,只能被类实现。一个类可以实现多个接口。抽象类:抽象类是一个不完全的类,它可以包含抽象方法和非抽象方法。抽象类不能被直接实例化,需要通过子类来继承并实现所有抽象方法。一个类只能继承一个抽象类。

  1. 方法与变量

接口:接口中只能定义抽象方法(从Java 8开始也可以定义默认方法和静态方法),所有方法默认都是public的。接口中定义的变量默认是public static final的。抽象类:抽象类中可以定义普通方法、抽象方法、静态方法、构造方法等,方法默认是public或protected的。抽象类中的变量可以是任何访问修饰符。

  1. 继承与实现

接口:一个类可以实现多个接口,通过关键字implements。抽象类:一个类只能继承一个抽象类,通过关键字extends

代码示例

接口

package com.demo.java.test.javacore;interface CanFight {void fight();
}interface CanSwim {void swim();
}interface CanFly {void fly();
}class ActionCharacter {public void fight2(){System.out.println("ActionCharacter fighting");}
}class Hero extends ActionCharacter implements CanFight, CanSwim, CanFly {public void swim() {System.out.println("swiming");}public void fly() {System.out.println("flying");}@Overridepublic void fight() {System.out.println("fighting");}
}public class Adventure {public static void t(CanFight x) {x.fight();}public static void u(CanSwim x) {x.swim();}public static void v(CanFly x) {x.fly();}public static void w(ActionCharacter x) {x.fight2();}public static void main(String[] args) {Hero h = new Hero();t(h); // Treat it as a CanFightu(h); // Treat it as a CanSwimv(h); // Treat it as a CanFlyw(h); // Treat it as an ActionCharacter}
}

  • 输出:

fighting
swiming
flying
ActionCharacter fighting

抽象类

以乐器类抽象举例,请看继承关系图

image

package com.demo.java.test.javacore;
// 音符枚举
enum Note{MIDDLE_C
}/***  乐器*/
abstract class Instrument {private int i; // Storage allocated for eachpublic abstract void play(Note n);public String what() {return "Instrument";}public abstract void adjust();
}/***  管乐器*/
class Wind extends Instrument {@Overridepublic void play(Note n) {System.out.println("Wind.play() " + n);}@Overridepublic String what() {return "Wind";}@Overridepublic void adjust() {System.out.println("Adjusting Wind");}
}/***  打击乐器*/
class Percussion extends Instrument {@Overridepublic void play(Note n) {System.out.println("Percussion.play() " + n);}@Overridepublic String what() {return "Percussion";}@Overridepublic void adjust() {System.out.println("Adjusting Percussion");}
}/***  有弦乐器*/
class Stringed extends Instrument {@Overridepublic void play(Note n) {System.out.println("Stringed.play() " + n);}@Overridepublic String what() {return "Stringed";}@Overridepublic void adjust() {System.out.println("Adjusting Stringed");}
}/***  铜管乐器*/
class Brass extends Wind {@Overridepublic void play(Note n) {System.out.println("Brass.play() " + n);}@Overridepublic void adjust() {System.out.println("Adjusting Brass");}
}class Woodwind extends Wind {@Overridepublic void play(Note n) {System.out.println("Woodwind.play() " + n);}@Overridepublic String what() {return "Woodwind";}
}/***  音乐组合类*/
public class Music4 {static void tune(Instrument i) {i.play(Note.MIDDLE_C);}static void tuneAll(Instrument[] e) {for (Instrument i: e) {tune(i);}}public static void main(String[] args) {// 向上转型Instrument[] orchestra = {new Wind(),new Percussion(),new Stringed(),new Brass(),new Woodwind()};// 演凑tuneAll(orchestra);}
}

  • 输出:

Wind.play() MIDDLE_C
Percussion.play() MIDDLE_C
Stringed.play() MIDDLE_C
Brass.play() MIDDLE_C
Woodwind.play() MIDDLE_C

文章转载自:一锤子技术员

原文链接:https://www.cnblogs.com/wikiman/p/18036728

体验地址:引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构

这篇关于Java面向对象之接口和抽象类的区别一目了然的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/756366

相关文章

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

Java中Redisson 的原理深度解析

《Java中Redisson的原理深度解析》Redisson是一个高性能的Redis客户端,它通过将Redis数据结构映射为Java对象和分布式对象,实现了在Java应用中方便地使用Redis,本文... 目录前言一、核心设计理念二、核心架构与通信层1. 基于 Netty 的异步非阻塞通信2. 编解码器三、

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

一篇文章彻底搞懂macOS如何决定java环境

《一篇文章彻底搞懂macOS如何决定java环境》MacOS作为一个功能强大的操作系统,为开发者提供了丰富的开发工具和框架,下面:本文主要介绍macOS如何决定java环境的相关资料,文中通过代码... 目录方法一:使用 which命令方法二:使用 Java_home工具(Apple 官方推荐)那问题来了,

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

Java中的.close()举例详解

《Java中的.close()举例详解》.close()方法只适用于通过window.open()打开的弹出窗口,对于浏览器的主窗口,如果没有得到用户允许是不能关闭的,:本文主要介绍Java中的.... 目录当你遇到以下三种情况时,一定要记得使用 .close():用法作用举例如何判断代码中的 input

Spring Gateway动态路由实现方案

《SpringGateway动态路由实现方案》本文主要介绍了SpringGateway动态路由实现方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随... 目录前沿何为路由RouteDefinitionRouteLocator工作流程动态路由实现尾巴前沿S