零基础Java第十五期:抽象类接口(一)

news2024/12/24 15:23:35

目录

一、抽象类

1.1. 抽象的概念

1.2. 抽象类语法 

1.3. 抽象类的特性 

1.4. 图形类例子 

二、 接口

2.1. 接口的概念

2.2. 语法规则 

2.3.  接口的特性

 2.4. 接口的使用

2.5. 实现多个接口

2.6. 工作当中常用的接口 


一、抽象类

1.1. 抽象的概念

       如果 一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。没有实际工作的方法, 我们可以把它设计成一个 抽象方法(abstract method), 包含抽象方法的类我们称为 抽象类(abstract class)。 

       就比如,Cat与Dog都属于Animal类,并且前两者与Animal都属于继承关系,但Animal不是一个具体的动物,也就无法实现.Bark()方法。

1.2. 抽象类语法 

        在Java中,一个类如果被 abstract 修饰称为抽象类,抽象类中被abstract 修饰的方法称为抽象方法,抽象方法不用给出具体的实现体。 

1.3. 抽象类的特性 

public abstract class Animal {
    public int age;
    public String name;

    public Animal(int age, String name) {
        this.age = age;
        this.name = name;
    }
    public void eat(){
        System.out.println(this.name+"正在吃饭");
    }
}

public class Dog extends Animal{
    public Dog(int age, String name) {
        super(age, name);
    }

    @Override
    public void eat() {
        System.out.println(this.name+"正在吃狗粮");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog(5,"泰克");
        Animal animal = new Animal()
    }
}

       就比如上面的代码中,Animal不是一个具体的动物,无法用成员变量对其进行赋值。那我们就可以在Animal这个类加上一个abstract,就把Animal变成抽象类,并且不能再new一个新对象。在抽象类中,如果一个方法没有具体的实现,前面就用abstract修饰。但如果一个类没有被抽象,那么这个类中就不能有抽象方法。

      如果一个类继承了一个抽象类,那么抽象类里的方法必须进行重写,否则就会报错(如下面的代码所示)。

public abstract class Animal {
    public int age;
    public String name;

    public abstract void eat(){//产生报错
        System.out.println(this.name+"be eating");
    }

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

public class Dog extends Animal{//产生报错
    public Dog(int age, String name) {
        super(age, name);
    }
    
}

      如果一个类继承了这个抽象类,然后不想重写抽象类当中的方法,只能把这个类也设置为抽象类。但最终还是得让一个普通类来继承这个抽象类,所以这些抽象方法最终都得被重写。

public abstract class Animal {
    public int age;
    public String name;

    public abstract void eat();

    public Animal(int age, String name) {
        this.age = age;
        this.name = name;
    }
}
public abstract class Dog extends Animal{//将Dog类也进行抽象化
    public Dog(int age, String name) {
        super(age, name);
    }
/*    @Override
    public void eat() {
        System.out.println(this.name+"吃狗粮");
    }*/不用再重写Animal类里的方法了
    public abstract void bark();
}

class Labrador extends Dog{//再用一个普通类继承Dog类

    public Labrador(int age, String name) {
        super(age, name);
    }

    @Override
    public void eat() {

    }

    @Override
    public void bark() {

    }
}

     而Labrador里面的这些方法怎么快速重写呢?将鼠标光标放在普通类后面,alt+回车,然后点击implement。但还是会出现报错,再次alt+回车,点击“Creat constructor……”,就能将成员变量重写,最后才能生成如上图所示的代码。

 

 

 

1.4. 图形类例子 

抽象类已经不能被实例化,但是还可以进行向上转型与多态。 

public abstract class Shape {
    public abstract void Draw();
}

public class Rect extends Shape{
    @Override
    public void Draw() {
        System.out.println("画一个矩形");
    }
}

public class Circle extends Shape{
    @Override
    public void Draw() {
        System.out.println("画一个圆");
    }
}

public class Flower extends Shape{
    @Override
    public void Draw() {
        System.out.println("花一朵花");
    }
}
public class Main {
    public static void DrawOut(Shape picture){
        picture.Draw();
    }

    public static void main(String[] args) {

        Flower flower = new Flower();
        DrawOut(flower);
        DrawOut(flower);
        DrawOut(flower);

        System.out.println("==========");
        DrawOut(new Flower());
        DrawOut(new Flower());
        DrawOut(new Flower());

    }
}

     运行结果如下: 虽然说打印结果一致,但其中的原理不同。

 

二、 接口

2.1. 接口的概念

     在现实生活中,接口的例子比比皆是,比如:笔记本上的USB口,电源插座等。电脑的USB口上,可以插:U盘、鼠标、键盘;所有符合USB协议的设备 电源插座插孔上,可以插:电脑、电视机、电饭煲...所有符合规范的设备。

      综上所述,接口就是公共的行为规范标准,大家在实现时,只要符合规范标准,就可以通用。 在Java中,接口可以看成是:多个类的公共规范,是一种引用数据类型。 

2.2. 语法规则 

public interface 接口名称 {

}

       我们如果点开out.目录底下的文件,可以找到接口对应的字节码文件,并且一个接口只对应一个字节码文件。接口名称一般以大写字母I开头,后面再跟一个形容词词性的单词。

2.3.  接口的特性

 (1)接口不能直接实例化

public interface IShape {
}

public class Main {
    public static void main(String[] args) {
        IShape iShape = new IShape();//产生报错
    }
}

(2)接口中的成员变量,默认是public static final修饰的

int a = 10;//默认为public static final
public int b = 20;
private int c = 30;//报错:Modifier 'private' not allowed here
public static final int d = 40;

(3)接口当中的方法,要是有具体的实现,就只能被static或default修饰,这些方法默认都是public 修饰的

public void test(){
   System.out.println("========");//Interface abstract methods cannot have body
}

default public void Hello(){
    System.out.println("========");
}

 (4)接口当中的方法,要是没有具体的实现,就要写成public static修饰的抽象方法,默认也为public static。

public abstract void World();//warning:Modifier 'public''abstract' is redundant for interface members
void DrawOut();

 2.4. 接口的使用

     一个类要想与与接口建立联系,要使用implements实现。实现之后,还要进行方法的重写。

public interface IShape {
    public abstract void World();
    void DrawOut();
}

public class Flower implements IShape{

    @Override
    public void DrawOut() {
        System.out.println("画一朵花");
    }
}

public class Main {
    public static void main(String[] args) {
        IShape iShape = new Flower();//通过向上转型来实例化

        iShape.DrawOut();
    }
}

2.5. 实现多个接口

       我们在上一期当中讲到了多态,多态能够降低代码的 "圈复杂度"。再有了接口之后, 类的使用者就不必关注具体类型, 而只关注某个类是否具备某种能力。这样我们在Main类里面再写一个Walk、Fly、Swim方法,无论有多少个参数,我们都能通过接口来进行传递。只要具备Walk、Fly、Swim这种能力的,我都能接受,不必关心什么类型的。

//父类对象
public 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();
}

//子类对象
public class Dog extends Animal implements ICanRun, ICanSwim {
    public Dog(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        System.out.println(this.name+"正在吃狗粮");
    }

    @Override
    public void run() {
        System.out.println(this.name+"正在跑");
    }

    @Override
    public void swim() {
        System.out.println(this.name+"正在游泳");
    }
}

public class Bird extends Animal implements ICanFly{
    public Bird(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {

    }

    @Override
    public void fly() {
        System.out.println(this.name+"正在飞");
    }
}
//接口
public interface ICanFly {
    void fly();
}

public interface ICanRun {
    void run();
}

public interface ICanSwim {
    void swim();
}
public class Main {
    public static void Fly(ICanFly canFly){
        canFly.fly();
    }
    public static void Walk(ICanRun canRun){
        canRun.run();
    }
    public static void Swim(ICanSwim canSwim){
        canSwim.swim();
    }

    public static void main(String[] args) {
        Dog dog = new Dog("斯派克",4);
        Bird bird = new Bird("金丝雀",1);
        Duck duck = new Duck("小黄鸭",1);
        Walk(duck);
        Walk(dog);
        System.out.println("===========");
        Swim(duck);
        Swim(dog);
        System.out.println("============");
        Fly(bird);
        Fly(duck);
    }
}

执行结果:

 

2.6. 工作当中常用的接口 

(1)引用类型的比较 

public class Student {
    public int age;
    public int score;
    public String name;

    public Student(int age, int score, String name) {
        this.age = age;
        this.score = score;
        this.name = name;
    }

    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", score=" + score +
                ", name='" + name + '\'' +
                '}';
    }

}

public class Main {
    public static void main(String[] args) {
        Student student1 = new Student(10,74,"张三");
        Student student2 = new Student(8,84,"李四");

        if(student1 > student2)//报错:Operator '>' cannot be applied to 'Student', 'Student'  Statement expected
    }
}

        <、>、=等关系运算符只能用于基本数据类型,在Java语法不支持地址的比较。要想实现引用类型的比较,就可以引入一个Comparable接口。我们看一下Comparable的源码,里面只有一个参数。同样需要重写一个方法。而我们要想进行比较,可以使用工具,比如我们新建一个AgeCompare类,需要接口Comparator,也需要重写方法。

public int compareTo(T o);
@Override
public int compareTo(Student o) {
    return 0;
}

如果我们想进行年龄的比较,就可以通过改返回值来进行比较。以下是完整代码:

//定义Student类
public class Student implements Comparable<Student>{
    public int age;
    public int score;
    public String name;

    public Student(int age, int score, String name) {
        this.age = age;
        this.score = score;
        this.name = name;
    }

    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", score=" + score +
                ", name='" + name + '\'' +
                '}';
    }

    @Override
    public int compareTo(Student o) {
        return 0;
    }
}
//比较的工具
import java.util.Comparator;

public class AgeCompare implements Comparator<Student> {

    @Override
    public int compare(Student o1, Student o2) {
        return o1.age - o2.age;
    }
}
public class Main {
    public static void main(String[] args) {
        Student student1 = new Student(10,74,"张三");
        Student student2 = new Student(8,84,"李四");
        System.out.println("进行年龄的比较");

        AgeCompare ageCompare = new AgeCompare();
        if(ageCompare.compare(student1,student2) > 0) {
            System.out.println("student1 > student2");
        }else {
            System.out.println("student1 < student2");
        }
    }
}

运行结果如下:

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2238401.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

13.UE5流星火雨,引导施法技能制作

2-15 流星火雨&#xff0c;引导施法技能制作、随机数_哔哩哔哩_bilibili 目录 1.为流星火雨添加按键映射 2.创建流星火雨的动画蒙太奇 3.实现播放动画蒙太奇的逻辑 ​编辑 4.定义发射一波流星火雨的发射物 5.使用动画通知释放流星火雨 1.为流星火雨添加按键映射 创建名为流…

让redis一直开启服务/自动启动

文章目录 你的redis是怎么打开的黑窗不能关?必须要自动启动吗?再说说mysql 本文的所有指令都建议在管理员权限下打开cmd控制台 推荐的以管理员身份打开控制台的方式 Win R 打开运行 输入cmdShift Ctrl Enter 你的redis是怎么打开的 安装过redis的朋友都知道, redis的安…

【安装配置教程】二、VMware安装并配置ubuntu22.04

一、准备&#xff1a; 虚拟机安装ubuntu&#xff0c;首先要先找到一个镜像&#xff0c;可以去ubuntu官方下载一个&#xff0c;地址&#xff1a;下载Ubuntu桌面系统 | Ubuntu&#xff0c;下载好iso的镜像文件后保存好&#xff0c;接下来打开VMware。 二、安装&#xff…

Latex中给公式加边框

1、这里使用的不是 amsmath 的 \boxed 命令, 而是 empheq 的 empheq 环境以及 xcolor 的 \fcolorbox 命令, 下面是代码, 可以分别阅读这两个手册来获取更多的信息 \documentclass{article} \usepackage{xcolor} \usepackage{empheq} \usepackage{amsmath} \begin{document}\be…

Android Parcelable和Serializable的区别与联系

在Android开发中&#xff0c;Parcelable和Serializable是两种用来在组件之间传递数据的序列化机制。它们有不同的使用场景和性能特点。 以下是它们之间的关系和区别&#xff1a; 1. 什么是 Parcelable Parcelable 是 Android 特有的接口&#xff0c;用于高效地在进程间传递数…

Android 实现柱形图

在 Android 中实现柱状图&#xff0c;可以使用流行的图表库 MPAndroidChart&#xff0c;它支持多种类型的图表&#xff0c;包括柱状图、折线图、饼图等。下面是一个基本的柱状图实现步骤&#xff0c;具体分为以下几个部分&#xff1a; 1. 添加依赖 首先&#xff0c;你需要在 …

通过交互式网页学习相机成像原理

​ 入门摄影这门艺术&#xff0c;你是否有以下这些问题&#xff1f; 焦距、光圈、CMOS是什么&#xff1f;为什么光圈越大&#xff0c;背景虚化效果越好&#xff1f;什么是过曝&#xff1f;… 今天我将分享一个简单的、可交互的相机成像模型&#xff0c;可供大家以可视化的方式…

web——sqliabs靶场——第一关

今天开始搞这个靶场&#xff0c;从小白开始一点点学习,加油&#xff01;&#xff01;&#xff01;&#xff01; 1.搭建靶场 注意点&#xff1a;1.php的版本问题&#xff0c;要用老版本 2.小p要先改数据库的密码&#xff0c;否则一直显示链接不上数据库 2.第一道题&#xff0…

自监督学习:机器学习的未来新方向

引言 自监督学习&#xff08;Self-Supervised Learning, SSL&#xff09;是近年来机器学习领域的一个重要发展方向&#xff0c;迅速成为许多研究和应用的热点。与传统的监督学习不同&#xff0c;自监督学习利用未标注数据&#xff0c;通过设计自我生成标签的任务&#xff0c;帮…

探索 HTML 和 CSS 实现的 3D 开关按钮

效果演示 这段代码是一个HTML和CSS的组合&#xff0c;用于创建一个3D风格的开关按钮&#xff08;通常用于控制某些设置的开启或关闭&#xff09; HTML <label class"switch"><input type"checkbox" checked"checked"><div cl…

车载诊断架构---NRC 78和NRC 21那些你不知道的事情!

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…

【计算机基础——数据结构——红黑树】

1. 红黑树&#xff08;RBTree&#xff09; 为什么HashMap不直接使用AVL树&#xff0c;而是选择了红黑树呢&#xff1f; 由于AVL树必须保证左右子树平衡&#xff0c;Max(最大树高-最小树高) < 1&#xff0c;所以在插入的时候很容易出现不平衡的情况&#xff0c;一旦这样&…

linux物理内存管理:node,zone,page

一、总览 对于物理内存内存&#xff0c;linux对内存的组织逻辑从上到下依次是&#xff1a;node&#xff0c;zone&#xff0c;page&#xff0c;这些page是根据buddy分配算法组织的&#xff0c;看下面两张图&#xff1a; 上面的概念做下简单的介绍&#xff1a; Node&#xff1a…

CKA认证 | 使用kubeadm部署K8s集群(v1.26)

一、前置知识点 1.1 生产环境可部署Kubernetes集群的两种方式 目前生产部署Kubernetes集群主要有两种方式&#xff1a; ① kubeadm Kubeadm是一个K8s部署工具&#xff0c;提供kubeadm init和kubeadm join&#xff0c;用于快速部署Kubernetes集群。 ② 二进制包 从github下…

如何安装和配置JDK17

教程目录 零、引言1、新特性概览2、性能优化3、安全性增强4、其他改进5、总结 一、下载安装二、环境配置三、测试验证 零、引言 JDK 17&#xff08;Java Development Kit 17&#xff09;是Java平台的一个重要版本&#xff0c;它带来了许多新特性和改进&#xff0c;进一步提升了…

第2章2.3立项【硬件产品立项的核心内容】

硬件产品立项的核心内容 2.3 硬件产品立项的核心内容2.3.1 第一步&#xff1a;市场趋势判断2.3.2 第二步&#xff1a;竞争对手分析1.竞争对手识别2.根据竞争对手分析制定策略 2.3.3 第三步&#xff1a;客户分析2.3.4 第四步&#xff1a;产品定义2.3.5 第五步&#xff1a;开发执…

一款革命性的视频剪辑工具,AI剪辑新纪元:Clapper

如果说AI视频剪辑工具哪家强&#xff1f;还真想不出有什么让人眼前一亮的AI视频剪辑应用。 毕竟随着AI技术的发展越来越快&#xff0c;各种AI应用如雨后春笋般涌现&#xff0c;然而&#xff0c;真正能够在视频剪辑领域脱颖而出的工具却寥寥无几。 今天我要介绍的 Clapper 就是…

递归函数学习 part1

一&#xff0c;初始递归&#xff1a;阶乘 1&#xff0c;原理 n的阶乘等于n乘以n-1的阶乘&#xff0c;而0的阶乘等于1. 2&#xff0c;代码展示 #include <iostream> using namespace std;int fact(int); int main() {cout<<fact(5);return 0; }int fact(int n) …

解决程序因缺少xinput1_3.dll无法运行的有效方法,有效修复丢失xinput1_3.dll

如果你的电脑在运行某些应用程序或游戏时提示“xinput1_3.dll丢失”或“找不到xinput1_3.dll”的错误消息&#xff0c;那么很可能是因为你的系统中缺少这个重要的DLL文件而导致的问题。那么电脑出现xinput1_3.dll丢失的问题时有哪些方法进行修复呢&#xff1f; 如何确定电脑是否…

深入了解区块链:Web3的基础架构与发展

在数字时代的浪潮中&#xff0c;区块链技术正逐渐成为Web3的重要基础&#xff0c;重新定义互联网的结构和用户体验。Web3不仅是一个全新的网络阶段&#xff0c;更代表了一种去中心化的理念&#xff0c;强调用户主权和数据隐私。本文将深入探讨区块链在Web3中的基础架构、技术特…