Java学习Day18:基础篇8

news2024/12/23 4:18:38

多态

基本信息:

应用场景:

可以把子类对象赋值给父类对象,实现多态从而使用同一种方法;

多态中调用成员的特点

1.调用成员变量都看左边

调用成员变量:编译看左边,运行也看左边 
编译看左边: javac编译代码的时候,会看左边的父类中有没有这个变量,如果有,编译成功,如果没有编译失败报错。
运行也看左边: java运 行代码的时候,实际获取的就是左边父类中成员变量的值

2.调用成员方法一左一右

调用成员方法:编译看左边,运行看右边

编译看左边: javac编译代码的时候,会看左边的父类中有没有这个方法,如果有,编译成功,如果没有报错

运行看右边: java运 行代码的时候,实际上运行的是子类中的方法。

3.成员变量和成员方法

成员变量:在子类的对象中,会把父类的成员变量也继承下的,所以使用的是弗雷德变量。

成员方法:如果子类对方法进行了重写,那么在虚方法表中是会把父类的方法进行覆盖的,所以调用成员方法输出就是成员重写的方法。

多态的优势

多态的弊端

不能调用子类的特有共能;

解决方案:强转回子类即可;

判断+转换+调用

小总结:

继承多态小案例:

package 多态的实例;
public abstract class Animal {
    private String colour;
    private int age;
    public Animal() {
    }
    public Animal(String colour, int age) {
        this.colour = colour;
        this.age = age;
    }
    public void eat(String something){
        System.out.println("吃"+something);
    }
    /**
     * 获取
     * @return name
     */
    public String getColour() {
        return colour;
    }
    /**
     * 设置
     */
    public void setColour(String colour) {
        this.colour = colour;
    }
    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }
    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }
    public String toString() {
        return "Animal{colour = " + colour+ ", age = " + age + "}";
    }
    public abstract void eat();
}
package 多态的实例;
public class Dog extends Animal{
    @Override
    public void eat(){
        System.out.println(getAge()+"岁"+getColour()+"颜色"+"的狗两只前腿死死的抱住骨头猛吃");
    }
    public void lookHome(){
        System.out.println("lookHome");
    }
}
package 多态的实例;
public class Cat extends Animal{
    @Override
    public void eat() {
    }
    public void catchMouse(){
        System.out.println("catchMouse");
    }
    public Cat() {
    }
    public Cat(String colour, int age) {
        super(colour, age);
    }
}
package 多态的实例;
public class Polymorphic_demo {
    public static void main(String[] args) {
        Person p =new Person();
        p.setName("老王");
        p.setAgeMan(33);
        Dog d =new Dog();
        d.setAge(3);
        d.setColour("黑色");
        Cat c =new Cat();
        c.setAge(2);
        c.setColour("黑白");
        p.grrenxinxi(d,"骨头");
        p.grrenxinxi(c,"粑粑");
    }
}

抽象类

抽象类(Abstract Class)是一种在编程语言中用于表示不能被实例化的类的概念。它的主要目的是提供一个或多个抽象方法(即没有实现体的方法,只有方法声明),这些方法必须由继承自抽象类的子类来实现。抽象类还可以包含已实现的方法(即具有方法体的方法)以及字段、属性、构造函数等。

抽象类的主要特点包括:

  1. 不能被实例化:抽象类不能直接创建对象,即不能使用new关键字来实例化抽象类。它的主要目的是被其他类继承,并由这些子类提供具体的实现。

  2. 包含抽象方法:抽象类可以包含一个或多个抽象方法。抽象方法是没有方法体的方法,只有方法的声明(即方法签名),并且必须以abstract关键字进行修饰。

  3. 允许包含非抽象方法和字段:除了抽象方法外,抽象类还可以包含已经实现的方法(即非抽象方法)以及字段、属性等。

  4. 子类必须实现父类的所有抽象方法:如果子类继承了一个抽象类,并且这个子类不是抽象类(即这个子类需要被实例化),那么子类必须实现父类中所有的抽象方法。否则,子类也必须被声明为抽象类。

  5. 作为类型引用:虽然不能直接实例化抽象类,但可以使用抽象类作为类型引用,指向其子类的实例。

抽象类在软件设计中非常有用,尤其是在实现多态和框架设计时。通过使用抽象类,可以定义一套接口规范,让不同的子类按照这套规范来实现具体功能,同时保证了代码的灵活性和可扩展性。

示例(以Java为例):

abstract class Animal {
// 抽象方法
abstract void eat();
// 已实现的方法
void sleep() {
System.out.println("This animal sleeps.");
}
}
class Dog extends Animal {
// 必须实现父类的抽象方法
@Override
void eat() {
System.out.println("Dog eats meat.");
}
}
public class Test {
public static void main(String[] args) {
Animal myDog = new Dog(); // 使用抽象类作为类型引用
myDog.eat(); // 调用Dog类实现的eat方法
myDog.sleep(); // 调用Animal类中已实现的sleep方法
}
}

抽象类的构造方法、成员方法和成员变量的几问

在Java中,抽象类(Abstract Class)与它的构造方法(Constructor)、成员变量(Member Variables)、以及成员方法(Member Methods,包括抽象方法和非抽象方法)之间有着特定的关系。下面分别解释这些关系:

构造方法(Constructor)

  • 构造方法的存在抽象类可以有构造方法。这些构造方法主要用于在创建子类对象时初始化父类(即抽象类)的成员变量
  • 构造方法的调用:当子类被实例化时,会首先调用父类(如果父类是抽象类)的构造方法(除非子类也是抽象类且仅被用作其他类的基类)。这是Java中对象初始化的一个基本步骤,确保父类被正确初始化。
  • 限制构造方法本身不能被声明为抽象abstract)。

成员变量(Member Variables)

  • 定义:抽象类可以定义成员变量,这些成员变量可以是任何类型(基本数据类型、对象引用等)。
  • 访问成员变量可以在抽象类的构造方法、成员方法(包括抽象方法和非抽象方法)中被访问和修改。同时,它们也可以被子类继承,并在子类中通过继承的super关键字或直接访问(如果它们不是私有的)来访问和修改

成员方法(Member Methods)

  • 抽象方法:抽象类中可以定义抽象方法,这些方法只有声明没有实现体(即方法体为空,并且使用abstract关键字修饰)。子类必须实现这些抽象方法,除非子类也是抽象类
  • 非抽象方法:抽象类中也可以定义非抽象方法,这些方法有具体的实现体,可以直接被调用。这些非抽象方法可以被继承到子类,并在子类中被直接使用或重写。
  • 访问:成员方法(无论是抽象的还是非抽象的)都可以在抽象类的构造方法、其他成员方法中被调用(抽象方法除外,因为抽象方法没有实现体)。同时,这些方法也可以被子类继承,并在子类中通过继承或重写来使用。

小总结

  • 抽象类可以有构造方法,但构造方法本身不能是抽象的。
  • 抽象类可以定义成员变量,这些变量可以在构造方法、成员方法中被访问和修改。
  • 抽象类可以定义抽象方法和非抽象方法。抽象方法必须由子类实现(除非子类也是抽象类),而非抽象方法可以直接在子类中使用或重写。
  • 成员变量和成员方法(非抽象的)都可以被子类继承,并根据需要在子类中进行访问、修改或重写。

接口

在Java中,接口(Interface)是一种引用类型,是一种抽象的类型,用于指定一组方法规范,但不提供这些方法的具体实现。接口是一种形式上的契约它要求实现了该接口的类(称为接口的实现类或实现接口的类)必须遵循接口中定义的规范

接口的主要特点:

  1. 抽象性接口中的所有方法默认都是抽象的(在Java 8之前),即它们只有声明没有实现体。从Java 8开始,接口中可以包含带有实现体的默认方法和静态方法

  2. 继承性:接口可以继承另一个或多个接口,使用extends关键字。接口之间的继承是多继承的,即一个接口可以继承多个其他接口

  3. 多态性:接口是支持多态性的重要手段。通过接口,我们可以指向实现了该接口的任何对象的引用。

  4. 实现接口的类必须实现接口中的所有方法(在Java 8之前),除非该类是抽象类。从Java 8开始,如果一个类实现了接口,但它不想实现接口中的某个默认方法,它可以选择不覆盖该方法,而是直接使用接口中提供的默认实现

  5. 接口中不能包含实例变量,但可以包含常量(即使用public static final修饰的变量,但通常省略这些修饰符)。

  6. 接口中的方法默认是public,且不允许使用其他访问修饰符(如privateprotected或包级私有)。

  7. 接口可以包含嵌套接口、枚举和静态类(在Java 9之前,接口中只能包含静态内部类;从Java 9开始,接口中可以包含非静态内部类,但内部类不能是抽象的)。

接口的使用场景包括定义一组方法的规范,使不相关的类可以实现这个接口,从而实现多态性。例如,ListSetMap等Java集合框架中的接口定义了集合操作的标准方法,不同的类如ArrayListLinkedListHashMap等实现了这些接口,提供了不同的实现方式。

接口在Java编程中非常重要,它促进了代码的模块化可重用性可扩展性。通过定义接口,我们可以让不同的类按照相同的约定进行工作,而不需要知道这些类的具体实现细节。

Java如何表示接口:

public interface Animal {  
    // 这是一个抽象方法,默认是public abstract的  
    void eat();  
  
    // 接口中的常量,默认是public static final的  
    int AGE = 10;  
  
    // Java 8 引入的默认方法  
    default void sleep() {  
        System.out.println("This animal sleeps.");  
    }  
  
    // Java 8 引入的静态方法  
    static void info() {  
        System.out.println("This is an interface for animals.");  
    }  
}

public class Dog implements Animal {  
    // 必须实现接口中的抽象方法  
    @Override  
    public void eat() {  
        System.out.println("Dog is eating.");  
    }  
  
    // 可以选择性地覆盖接口中的默认方法  
    @Override  
    public void sleep() {  
        System.out.println("Dog is sleeping in a doghouse.");  
    }  
  
    // 静态方法和常量可以直接通过接口名访问,无需实现  
    public static void main(String[] args) {  
        Animal.info(); // 直接访问接口的静态方法  
        System.out.println(Animal.AGE); // 直接访问接口的常量  
  
        Dog dog = new Dog();  
        dog.eat();  
        dog.sleep(); // 调用的是Dog类中覆盖的sleep方法  
    }  
}

接口实例化(虽然不能直接实例化抽象类,但可以使用抽象类作为类型引用,指向其子类的实例。)

// 定义接口  
public interface Animal {  
    void eat();  
    void sleep();  
}  
  
// 实现接口  
public class Dog implements Animal {  
    @Override  
    public void eat() {  
        System.out.println("Dog is eating.");  
    }  
  
    @Override  
    public void sleep() {  
        System.out.println("Dog is sleeping.");  
    }  
}  
  
// 在另一个类中实例化Dog类  
public class Main {  
    public static void main(String[] args) {  
        // 实例化Dog类,但可以将实例引用视为Animal类型  
        Animal myDog = new Dog();  
  
        // 调用接口中定义的方法,但实际上是调用Dog类中的实现  
        myDog.eat();  
        myDog.sleep();  
  
        // 注意:你不能直接实例化接口,下面的代码会编译错误  
        // Animal anotherAnimal = new Animal(); // 错误:接口不能被实例化  
    }  
}
在这个例子中,Dog类实现了Animal接口,所以我们可以通过new Dog()来创建一个Dog对象。但是,由于Dog实现了Animal接口,我们可以将这个Dog对象的引用视为Animal类型(即Animal myDog = new Dog();)。这允许我们在不直接依赖于具体类(Dog)的情况下编写更灵活和可重用的代码。我们可以将myDog引用传递给期望Animal类型参数的任何方法或函数,只要这些方法或函数不依赖于Animal接口中未由Dog类实现的任何额外方法。

接口的成员方法和成员变量

成员方法

接口中的成员方法默认是public abstract,这意味着它们必须被实现接口的类所实现(除非该类也是抽象的)。然而,从Java 8开始,接口还可以包含默认方法(使用default关键字)和静态方法(使用static关键字)。

  • 抽象方法:没有方法体的方法,必须由实现接口的类提供具体实现。
  • 默认方法:提供了一种方式,允许接口在不破坏向后兼容性的情况下添加新的方法实现。
  • 静态方法:可以直接通过接口名来调用,不需要实现接口的类实例。

成员变量

接口中的成员变量实际上是常量,因为它们在接口中默认是public static final的。这意味着你可以直接通过接口名来访问这些常量,而不需要创建接口的实例。

使用示例

// 定义一个接口
public interface Animal {
// 成员变量(实际上是常量)
int MAX_AGE = 100;
// 抽象方法
void eat();
// 默认方法
default void sleep() {
System.out.println("This animal sleeps.");
}
// 静态方法
static void info() {
System.out.println("This is an interface for animals.");
}
}
// 实现接口的类
public class Dog implements Animal {
@Override
public void eat() {
System.out.println("Dog is eating.");
}
// 可以选择性地覆盖默认方法
@Override
public void sleep() {
System.out.println("Dog is sleeping in a doghouse.");
}
// 使用接口中的常量
public void printMaxAge() {
System.out.println("The maximum age of an animal is " + Animal.MAX_AGE);
}
}
// 在另一个类中测试
public class Main {
public static void main(String[] args) {
// 访问静态方法
Animal.info();
// 实例化Dog类
Dog myDog = new Dog();
// 调用抽象方法的实现
myDog.eat();
// 调用默认方法(可能被覆盖)
myDog.sleep();
// 调用打印常量的方法
myDog.printMaxAge();
}
}

在这个例子中,Animal接口定义了一个常量MAX_AGE、一个抽象方法eat()、一个默认方法sleep()和一个静态方法info()Dog类实现了Animal接口,并提供了eat()方法的具体实现,同时覆盖了sleep()默认方法。在Main类中,我们展示了如何通过接口名直接访问静态方法和常量,以及如何通过实现接口的类实例来调用抽象方法和默认方法。

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

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

相关文章

【BSV生态亮点】体育进入区块链时代:波兰奥委会与Zetly建立战略伙伴关系

​​发表时间:2024年7月18日 波兰奥运委员会和Zetly宣布正式建立战略伙伴关系。这一合作是波兰将现代技术、数字资产和创新解决方案整合到波兰体育中的重要一步,将把波兰体育产业带入数字时代。 Zetly是一个非常活跃的数字平台,它将体育与区…

3.6.锚框

锚框 ​ 13.4. 锚框 — 动手学深度学习 2.0.0 documentation (d2l.ai) ​ 一类目标检测算法是基于锚框的,步骤如下: ​ 使用多个被称为锚框的区域(边缘框),预测每个锚框里是否含有关注的物体,如果有,则预测从这个锚…

双指针-【3,4,5,6,7,8】

第三题:快乐数 . - 力扣(LeetCode). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/happy-number/算法思想: 1.每个…

jdk版本管理利器-sdkman

1.什么是sdkman? sdkman是一个轻量级、支持多平台的开源开发工具管理器,可以通过它安装任意主流发行版本(例如OpenJDK、Kona、GraalVM等等)的任意版本的JDK。通过下面的命令可以轻易安装sdkman: 2.安装 curl -s "https://…

IFM易福门LR3000LR3300液位传感器操作说明

IFM易福门LR3000LR3300液位传感器操作说明

使用ssh-remote连接远程vscode运行yolo项目时的一点坑

使用ssh-remote连接远程vscode运行yolo项目时的一点坑 1.坑1 因为我是直接下载的release包,然后运行 pip install -e .来下载依赖的,那么这个时候需要使用YOLO时都需要在下载的release文件的目录下的py文件才能生效 比方说我下载的yolov8(ultralytic…

SpringBoot 快速上手

1. 环境准备 ⾃检Idea版本: 社区版: 2021.1 -2022.1.4 专业版: ⽆要求 如果个⼈电脑安装的idea不在这个范围, 需要卸载重新安装. Idea 卸载参考: https://blog.csdn.net/qq_19072921/article/details/126408402 (⼀定要删除注册表) 2. Maven 2.1 什么是Maven 官⽅…

Stable Diffusion 模型的安装和使用

一、SD模型简介 Stable Diffusion的绘图风格主要由模型来控制,基础模型主要由二次元图片训练获得,所以在不安装其他模型的情况下,只能生成二次元风格的图像。 模型能够有效地控制生成的画风和内容。 常用的模型网站有: Stable D…

Taro 框架中使用iconfont 阿里巴巴矢量图标 class版

想必大家都知道这个图标库的 图标还是很多的‘ 大家应该都也用过 最进开发 Taro nut-ui 的H5 移动端的时候 我发现一些图标我在组件库中找不到 我看到了nut-ui 中还有另一种使用方法 这个叫做 自定一图标 、 我来用实际操作 代码 来介绍一下 这个怎么使用 我总结文章 …

docker环境安装kafka/Flink/clickhouse镜像

1、安装Kafka服务 1、将一下三个tar文件复制到ubuntu指定目录下 2、进入到/home/cl/app目录,使用docker命令加载tar镜像文件 # cd /home/cl/app # docker load -i kafka.tar # docker load -i kafka-manager.tar # docker load -i kafka-zookeeper.tar3、查看d…

MySQL基础练习题11-换座位

题目:交换每两个连续的学生的座位号。如果学生的数量是奇数,则最后一个学生的id不交换。按 id 升序 返回结果表。 准备数据 分析数据 方法一:利用power函数对id进行交换,得出的答案只有0或1 第一步:用power()函数将…

HDBaseT远距离无压缩传输系统源头厂家

HDBaseT双绞线延长器是一款集成HDBaseT的远距离高清信号无压缩、无延时传输器,HDMI信号从接收端输出, 信号分辨率高达4Kx2K可以通过单根CAT5/CAT6网线将信号长距离传输高清无压缩音视频信号, 采用单根网线最远可传输70/100米, …

Linux 安装 nacos 2.4.0

参看:Nacos 快速开始 2.4.0 版本是Nacos2.X的又一个功能性版本,此版本的更新主要在 Nacos 的安全性、扩展功能和改进用户体验方面的持续努力,为用户提供了更安全、更灵活的服务管理平台。版本主要的功能如下: 增强安全性&#xf…

Duix AI 太上瘾,让我熬夜体验的AI女友

✨点击这里✨:🚀原文链接:(更好排版、视频播放、社群交流、最新AI开源项目、AI工具分享都在这个公众号!) Duix AI 太上瘾,让我熬夜体验的AI女友 开启 Duix AI 女友的奇妙之旅_ Hi,这…

C++:类和对象2

1.类的默认成员函数 默认成员函数就是用户没有显示实现编译器会自动生成的成员函数称为默认成员函数。一个类,我们在不写的情况下编译器会默认生成6个默认成员函数,分别是构造函数,析构函数,拷贝构造函数,拷贝赋值运算…

前缀和与差分大总结!!!C++

学了忘忘了学o(╥﹏╥)o 题源acwing 讲解前缀和一维,用于序列二维,用于矩阵 讲解差分什么是差分数组?一维差分数组二维差分数组 题目一:前缀和题目二:子矩阵的和题目三:差分题目四:差分矩阵 讲…

案例分享-国外轻松感UI设计赏析

国外UI设计倾向于采用简洁的布局、清晰的排版和直观的交互方式,减少用户的认知负担,从而营造出轻松的使用体验。这种设计风格让用户能够快速找到所需信息,降低操作难度,提升整体满意度。 在注重美观的同时,更加重视用户…

便携移动工作站,端侧 AI 大模型设备折腾笔记:ROG 幻 X 和 4090 扩展坞

为了本地测试和开发更丝滑,最近入手了一套新设备 ROG 幻 X Z13 和 ROG XG Mobile 4090 扩展坞。 基于这套设备,我搭了一套 Windows x WSL2 x CUDA 的开发环境。分享一下折腾记录,或许对有类似需求的你也有帮助。 写在前面 最近因为各种事情…

【MySQL】索引 【下】{聚簇索引VS非聚簇索引/创建主键索引/全文索引的创建/索引创建原则}

文章目录 1.聚簇索引 VS 非聚簇索引经典问题 2.索引操作创建主键索引唯一索引的创建普通索引的创建全文索引的创建查询索引删除索引索引创建原则 1.聚簇索引 VS 非聚簇索引 之前介绍的将所有的数据都放在叶子节点的这种存储引擎对应的就是 InnoDB 默认存储表数据的存储结构。 …

【大模型系列】Video-LaVIT(2024.06)

Paper:https://arxiv.org/abs/2402.03161Github:https://video-lavit.github.io/Title:Video-LaVIT: Unified Video-Language Pre-training with Decoupled Visual-Motional TokenizationAuthor:Yang Jin, 北大&#x…