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

Java——面向对象进阶(三)

在这里插入图片描述

前言:
抽象类,接口,内部类


文章目录

  • 一、抽象类
    • 1.1 抽象方法
    • 1.2 抽象类
    • 1.3 抽象类的使用
  • 二、 接口
    • 2.1 接口的定义和实现
    • 2.2 default 关键字
    • 2.3 实现接口时遇到的问题
  • 三、内部类
    • 3.1 成员内部类
    • 3.2 静态内部类
    • 3.3 成员内部类
    • 3.4 匿名内部类(最常用)

一、抽象类

在Java中,抽象类是一种不能被实例化的类,它通常用于定义一些共用的方法和字段,在该类中不知道具体的实现,但还是想让子类必须去实现这些方法,所以将成员方法定义成抽象方法,该类定义成抽象类。abstract 用于修饰方法方法和类,修饰的方法是抽象方法,修饰的类是抽象类。

1.1 抽象方法

使用abstract 关键字修饰方法,该方法就成了抽象方法,抽象方法只包含一个方法名,而没有方法体。

定义格式:
修饰符 abstract 返回值类型 方法名 (参数列表);示例:
public abstract void run();

1.2 抽象类

使用abstract 关键字修饰类,

形式:
abstract class 类名字 { }示例:
public abstract class Animal {public abstract void run()}

!注意:抽象类不一定有抽象方法,但有抽象方法的类一定要定义成抽象类

1.3 抽象类的使用

  1. 继承抽象类:

    • 如果一个类继承了一个抽象类,并且这个类不是抽象类,那么它必须实现所有从抽象类继承的抽象方法。
    • 如果一个类继承了一个抽象类,但没有实现所有的抽象方法,那么这个类必须声明为抽象类。
  2. 抽象类的继承链:

    • 一个抽象类可以继承另一个抽象类,并且可以选择性地实现部分或全部继承的抽象方法。
    • 最终,必须有一个具体(非抽象)的子类实现所有抽象方法。

示例代码:

  1. 子类实现所有抽象方法

    abstract class Animal {abstract void makeSound();abstract void eat();
    }class Dog extends Animal {@Overridevoid makeSound() {System.out.println("Woof!");}@Overridevoid eat() {System.out.println("Dog is eating.");}
    }public class Main {public static void main(String[] args) {Animal myDog = new Dog();myDog.makeSound();myDog.eat();}
    }
    

    Dog类继承了Animal类,并且实现了所有的抽象方法。

  2. 子类没有实现所有抽象方法,必须声明为抽象类

    abstract class Animal {abstract void makeSound();abstract void eat();
    }abstract class Canine extends Animal {@Overridevoid makeSound() {System.out.println("Howl!");}// `eat` 方法没有实现,所以 Canine 仍然是抽象类
    }class Dog extends Canine {@Overridevoid eat() {System.out.println("Dog is eating.");}
    }public class Main {public static void main(String[] args) {Animal myDog = new Dog();myDog.makeSound();myDog.eat();}
    }
    

    Canine类实现了makeSound方法,但没有实现eat方法,因此Canine必须声明为抽象类。Dog类继承了Canine并实现了eat方法,使得Dog成为具体类,可以被实例化。


二、 接口

接口(Interface)在Java中是一个重要的概念,用于定义一组方法的规范,而不提供任何实现。接口主要用于定义类之间的契约和规范,确保实现这些接口的类遵循相同的方法签名。

2.1 接口的定义和实现

接口的定义:
接口使用interface关键字定义,接口中的所有方法默认是publicabstract,所有成员变量默认是public static final。以下是一个简单的接口示例:

public interface Animal {void makeSound();void eat();
}

实现接口
类通过implements关键字实现接口,一个类可以实现多个接口,这与抽象类的单继承限制不同。以下是实现Animal接口的两个类:

public class Dog implements Animal {@Overridepublic void makeSound() {System.out.println("Woof!");}@Overridepublic void eat() {System.out.println("Dog is eating.");}
}public class Cat implements Animal {@Overridepublic void makeSound() {System.out.println("Meow!");}@Overridepublic void eat() {System.out.println("Cat is eating.");}
}

类实现接口的要求:

  1. 必须重写实现的全部接口中所有抽象方法。
  2. 如果一个类实现了接口,但是没有重写完全部接口的全部抽象方法,这个类也必须定义成抽象类。

如果一个类实现了多个接口,而这些接口有相同的抽象方法,那么这个类只需要实现这个抽象方法一次即可,因为Java不允许同一个类中出现重复的方法签名。这种情况下,类只需要提供一次方法的实现,而不需要重复实现多次。


2.2 default 关键字

default 关键字主要用于接口中的默认方法(default methods),这是从Java 8开始引入的特性。默认方法允许在接口中为方法提供默认的实现,这样可以在不破坏现有实现的情况下,向接口添加新的方法。

默认方法(Default Methods)定义方式:

public interface InterfaceName {// 抽象方法void regularMethod();// 默认方法default void defaultMethod() {// 默认实现System.out.println("This is a default method.");}
}

在上面的例子中,defaultMethod 就是一个默认方法。默认方法使用 default 关键字修饰,它提供了一个默认的实现。所有实现了这个接口的类都会继承这个默认方法,如果需要的话,可以在实现类中重写默认方法。

示例:

public interface Vehicle {void start();default void honk() {System.out.println("Vehicle is honking.");}
}public class Car implements Vehicle {@Overridepublic void start() {System.out.println("Car is starting.");}// Car可以选择不重写honk方法,使用默认实现
}public class Bike implements Vehicle {@Overridepublic void start() {System.out.println("Bike is starting.");}@Overridepublic void honk() {System.out.println("Bike is honking."); // Bike提供了自己的honk方法实现}
}

当需要扩展一个接口,但又不能破坏所有实现这个接口的类时,可以使用默认方法。

注意事项:
如果一个类实现了多个接口,而这些接口有相同的默认方法,实现类必须重写这个默认方法来解决冲突。

interface A {default void hello() {System.out.println("Hello from A");}
}interface B {default void hello() {System.out.println("Hello from B");}
}class C implements A, B {@Overridepublic void hello() {A.super.hello(); // 明确指定调用接口A的默认方法//B.super.hello(); 或明确指定调用接口B的默认方法}
}

2.3 实现接口时遇到的问题

  1. 如果一个类继承了一个类并实现了一个接口,且父类和接口中有都有相同签名的方法。

    • 处理办法一:如果父类中的方法体,能满足当前业务的需求,在子类中可以不用重写。
    • 处理办法二:如果父类中的方法体,不能满足当前业务的需求,需要在子类中重写。
  2. 如果一个接口中,有多个抽象方法,但在实现类中,只需要用其中一个或部分

    • 方法一:实现类声明为抽象类
      你可以将实现类声明为抽象类,并只实现部分抽象方法,这样子类就可以根据需要选择性地实现接口的方法。

      // 定义一个接口
      interface MyInterface {void method1(); // 抽象方法1void method2(); // 抽象方法2void method3(); // 抽象方法3
      }// 实现类声明为抽象类,并只实现部分方法
      abstract class MyAbstractClass implements MyInterface {@Overridepublic void method1() {System.out.println("Implemented method1");}// 不需要实现 method2 和 method3
      }// 子类继承抽象类,选择性实现部分方法
      class MyClass extends MyAbstractClass {@Overridepublic void method2() {System.out.println("Implemented method2");}
      }
      
    • 方法二:使用适配器模式(Adapter Pattern)
      如果不想使用抽象类,可以使用适配器模式,它允许提供接口的默认实现,然后子类可以选择性地覆盖它们。

      // 定义一个接口
      interface MyInterface {void method1(); // 抽象方法1void method2(); // 抽象方法2void method3(); // 抽象方法3
      }// 创建适配器类,提供接口的默认实现
      abstract class MyInterfaceAdapter implements MyInterface {@Overridepublic void method1() {// 默认实现}@Overridepublic void method2() {// 默认实现}@Overridepublic void method3() {// 默认实现}
      }// 子类选择性地覆盖需要的方法
      class MyClass extends MyInterfaceAdapter {@Overridepublic void method2() {System.out.println("Implemented method2");}
      }
      

三、内部类

内部类(Inner Class)是定义在另一个类内部的类。Java 提供了多种内部类,包括成员内部类、局部内部类、匿名内部类和静态内部类。

按定义的位置来分:

  1. 成员内部内,类定义在了成员位置 (类中方法外称为成员位置,无static修饰的内部类)
  2. 静态内部类,类定义在了成员位置 (类中方法外称为成员位置,有static修饰的内部类)
  3. 局部内部类,类定义在方法内
  4. 匿名内部类,没有名字的内部类,可以在方法中,也可以在类中方法外。

3.1 成员内部类

定义格式:

class OuterClass {class InnerClass {// Inner class members}
}

内部类的使用格式

 外部类.内部类。 // 访问内部类的类型都是用 外部类.内部类

创建内部类实例:

  • 方式一:外部直接创建成员内部类的对象

    OuterClass outer = new OuterClass();
    OuterClass.InnerClass inner = outer.new InnerClass();
    //或
    OuterClass.InnerClass inner = new OuterClass().new InnerClass();
    
  • 方法二:在外部类中定义一个方法提供内部类的对象

    public class Outer {private class Inner{}public Inner getInstance(){return new Inner();}
    }public class Test {public static void main(String[] args) {Outer outer = new Outer();Inner inner = outer.getInstance();}
    }
    

成员内部类的细节

  1. 成员内部类可以被一些修饰符所修饰,比如: private,默认,protected,public,static等

  2. 成员内部类可以访问外部类的所有成员,包括私有成员。这是因为成员内部类持有一个对外部类实例的引用Outer.this

    public class Outer {private String outerField = "Outer field";class Inner {void display() {System.out.println("Inner class accessing: " + outerField);System.out.println("Inner class accessing through Outer.this: " + Outer.this.outerField);}}public static void main(String[] args) {Outer outer = new Outer(); // 创建外部类对象Outer.Inner inner = outer.new Inner(); // 创建内部类对象inner.display(); // 调用内部类的方法}
    }//输出:
    Inner class accessing: Outer field
    Inner class accessing through Outer.this: Outer field
    

    内存图示例:内存图示例

  3. 在 JDK 8 之前,局部变量必须显式声明为 final 才能被成员内部类。在 JDK 8 及之后,只要局部变量在初始化后没有被修改,它们就被隐式地视为 final(即有效 final),不再需要显式声明为 final。


3.2 静态内部类

定义格式:

class OuterClass {static class StaticInnerClass {// 静态内部类的成员}
}

创建实例:

OuterClass.StaticInnerClass innerObject = new OuterClass.StaticInnerClass();

静态内部类的特点

  1. 静态内部类可以直接访问外部类的静态成员,但不能访问外部类的非静态成员,如果要访问需要创建外部类的对象,用对象调用。

    public class Outer {private static String staticOuterField = "Static Outer Field";private String nonStaticOuterField = "Non-Static Outer Field";static class StaticInner {void display() {// 静态内部类可以访问外部类的静态成员System.out.println("Static Inner Class accessing static outer field: " + staticOuterField);// 但不能直接访问外部类的非静态成员// System.out.println("Static Inner Class accessing non-static outer field: " + nonStaticOuterField); // 编译错误}}public static void main(String[] args) {// 创建静态内部类的实例StaticInner inner = new StaticInner();inner.display(); // Output: Static Inner Class accessing static outer field: Static Outer Field// 如果要访问外部类的非静态成员,需要创建外部类的对象Outer outer = new Outer();System.out.println("Access non-static outer field through outer object: " + outer.nonStaticOuterField);}
    }
    
  2. 无需外部类实例: 可以直接创建静态内部类的实例,而不需要外部类的实例。

  3. :静态内部类中没有隐含的 Outer.this


3.3 成员内部类

局部内部类是定义在方法或作用域内部的内部类。

特点

  • 作用域限制: 局部内部类的作用域仅限于定义它的方法或代码块中,不能在外部访问。
  • 访问权限: 局部内部类可以访问外部类的所有成员,包括私有成员。
  • 访问局部变量: 局部内部类可以访问方法内的 final 局部变量(JDK 8+版本可以访问非 final 的局部变量,但其值不能在局部类中被修改)。
  • 生命周期: 局部内部类的生命周期仅限于方法调用,方法结束后局部内部类实例也会被销毁。

示例

public class Outer {private int outerField = 10;public void methodWithLocalInnerClass() {final int localVar = 20; // JDK 8+ 可以不用final修饰,但不可变class LocalInner {void display() {System.out.println("Outer field: " + outerField);System.out.println("Local variable: " + localVar);}}// 创建局部内部类的实例并调用方法LocalInner inner = new LocalInner();inner.display();}public static void main(String[] args) {Outer outer = new Outer();outer.methodWithLocalInnerClass();}
}

3.4 匿名内部类(最常用)

匿名内部类是一种没有显式声明类名的内部类,它在创建对象的同时定义类的实现。匿名内部类通常用于创建只需使用一次且没有额外的逻辑的类实例。

格式:

new 类名或者接口名() {重写方法;
};
这里同时包含了继承或实现,方法重写,创建对象
从new关键字到";"整个整体是匿名内部类的实例,"{}"内的是匿名内部类,没有类名

使用:
以接口为例,匿名内部类的使用,代码如下:

interface Swim {public abstract void swimming();
}public class Test {public static void main(String[] args) {// 接口 变量 = new 实现类(); // 多态,走子类的重写方法Swim s2 = new Swim() {@Overridepublic void swimming() {System.out.println("蛙泳...");}};s2.swimming();}
}


如果你喜欢这篇文章,点赞👍+评论+关注⭐️哦!
欢迎大家提出疑问,以及不同的见解。

相关文章:

Java——面向对象进阶(三)

前言: 抽象类,接口,内部类 文章目录 一、抽象类1.1 抽象方法1.2 抽象类1.3 抽象类的使用 二、 接口2.1 接口的定义和实现2.2 default 关键字2.3 实现接口时遇到的问题 三、内部类3.1 成员内部类3.2 静态内部类3.3 成员内部类3.4 匿名内部类&a…...

鸿蒙开发电话服务:【@ohos.telephony.observer (observer)】

observer 说明: 本模块首批接口从API version 6开始支持。后续版本的新增接口,采用上角标单独标记接口的起始版本。 导入模块 import observer from ohos.telephony.observerobserver.on(‘networkStateChange’) on(type: ‘networkStateChange’, ca…...

希亦、追觅、云鲸洗地机:究竟有何不同?选择哪款更合适

最近收到很多私信里,要求洗地机测评的呼声特别高,作为宠粉的测评博主,当然是马上安排起来,满足大家对想看洗地机的愿望。这次洗地机测评,我挑选了三款热门的品牌型号,并从多个维度对它们进行使用测评&#…...

代码随想录算法训练营第二十六天

题目:455. 分发饼干 贪心第一题 这里的局部最优就是大饼干喂给胃口大的,充分利用饼干尺寸喂饱一个,全局最优就是喂饱尽可能多的小孩。或者小饼干先喂饱小胃口 首先要对 g 和 s进行排序这样才能知道最大的胃口和最大的饼干然后进行遍历即可…...

[面试题]Java【并发】

[面试题]Java【基础】[面试题]Java【虚拟机】[面试题]Java【并发】[面试题]Java【集合】[面试题]MySQL 因为 Java 并发涉及到的内容会非常多,本面试题可能很难覆盖到所有的知识点,所以推荐 《Java并发编程的艺术》 。 Java 线程 线程 通知 等待 线…...

基于VSCode和MinGW-w64搭建LVGL模拟开发环境

目录 概述 1 运行环境 1.1 版本信息 1.2 软件安装 1.2.1 下载安装VS Code 1.2.1.1 下载软件 1.2.1.1 安装软件 1.2.2 下载安装MinGW-w64 1.2.2.1 下载软件 1.2.2.2 安装软件 1.2.3 下载安装SDL 1.2.3.1 下载软件 ​1.2.3.2 安装软件 1.2.4 下载安装CMake 1.2.4.…...

H5112B 降压恒流芯片12V24V36V48V60V72V100V 1.2ALED 调光无频闪光滑细腻

H5112B多功能LED恒流驱动器是一款具有良好性能与高度集成度的驱动芯片。以下是该产品的主要优点及应用领域的详细分析: 产品优点: 宽电压输入范围:H5112B支持5V至90V的宽电压输入范围,使其能够适应多种不同的电源环境&#xff0…...

真心建议大家冲一冲新兴领域,工资高前景好【大模型NLP开发篇】

前言 从ChatGPT到新近的GPT-4,GPT模型的发展表明,AI正在向着“类⼈化”⽅向迅速发展。 GPT-4具备深度阅读和识图能⼒,能够出⾊地通过专业考试并完成复杂指令,向⼈类引以为傲的“创造⼒”发起挑战。 现有的就业结构即将发⽣重⼤变…...

深度剖析淘宝扭蛋机源码:打造趣味性电商活动的秘诀

在当今电商市场中,如何吸引用户的注意力、提升用户的参与度成为了各大电商平台竞相追求的目标。淘宝扭蛋机作为一种新型的电商活动形式,以其趣味性和互动性深受用户喜爱。本文将深度剖析淘宝扭蛋机源码,探讨其如何打造趣味性与互动性并存的电…...

vue3+优化vue-baidu-map中marker点过多导致的页面卡顿问题

场景: 移动端h5中,当我们需要在地图中展示很多marker点坐标的时候,通常会使用 bm-marker ,去循环生成marker点,在数量不多的情况下是没问题的,但是随着数据量的增加,地图就会变得卡顿,以及渲染延…...

PMS助力制造企业高效运营︱PMO大会

全国PMO专业人士年度盛会 北京易贝恩项目管理科技有限公司副总经理朱洪泽女士受邀为PMO评论主办的2024第十三届中国PMO大会演讲嘉宾,演讲议题为“PMS助力制造企业高效运营”。大会将于6月29-30日在北京举办,敬请关注! 议题简要: …...

认识一些分布-关于极值点分布的一些知识

可以参考下面资料: Extreme Value Distribution & the Extreme Value Theory - Statistics How To...

Anaconda环境安装失败的解决方案

链接步骤的补充。 为了运行marlib,需要一个全新的Anaconda环境。但是,不想把文件安装在C盘,会造成空间不足。于是试着在.condarc文件里面改动了路径,具体如图。 上图中,在defaults前面添加了D盘的路径作为安装路径。 …...

mac 本地启动rocketmq

Mac 本地起rocketmq 官网下载:RocketMq官网下载地址 下载后解压 如果电脑配置不高或者不希望rocketmq占用太大内存的,修改配置/bin/runbroker.sh JAVA_OPT"${JAVA_OPT} -server -Xms512m -Xmx512m -Xmn256m"-Xmx4g 初始堆大小 4g -Xms4g 最大…...

数据资产管理的未来趋势:洞察技术前沿,探讨数据资产管理在云计算、大数据、区块链等新技术下的发展趋势

一、引言 随着信息技术的飞速发展,数据已成为企业最重要的资产之一。数据资产管理作为企业核心竞争力的关键组成部分,其发展趋势和技术创新受到了广泛关注。特别是在云计算、大数据、区块链等新技术不断涌现的背景下,数据资产管理面临着前所…...

lwip中server和client的socket、地址和端口号

1、server的socket通过lwip_socket建立: server_sd lwip_socket(AF_INET, SOCK_STREAM, 0);2、client的socket在监听到连接后建立: client_sd lwip_accept(server_sd, (struct sockaddr *)&client_addr_port, (socklen_t *)&size);3、server…...

代码随想录算法训练营Day38|动态规划理论基础、2.斐波那契数、3.爬楼梯、4.使用最小花费爬楼梯

动态规划理论基础 代码随想录 (programmercarl.com) 动态规划(Dynamic Programming,简称DP)是一种算法设计技术,它通过将复杂问题分解为更小的子问题来解决优化问题。动态规划通常用于解决那些具有重叠子问题和最优子结构特性的…...

IIC通信总线

文章目录 1. IIC总线协议1. IIC简介2. IIC时序1. 数据有效性2. 起始信号和终止信号3. 数据格式4. 应答和非应答信号5. 时钟同步6. 写数据和读数据 2. AT24C023. AT24C02读写时序4. AT24C02配置步骤5. 代码部分1. IIC基本信号2. AT24C02驱动代码3. 实验结果分析 1. IIC总线协议 …...

2024 年最新 Python 调用 OpenAi 详细教程实现问答、图像合成、图像理解、语音合成、语音识别(详细教程)

OpenAi 环境安装 首先确保您的计算机上已经安装了 Python。您可以从 Python 官方网站下载并安装最新版本 Python。安装时,请确保勾选 “Add Python to PATH” (添加环境变量)选项,以便在 cmd 命令行中直接使用 Python。 安装 Op…...

git原理解释,windows 10 / ubuntu 24.04 安装使用 github

git的原理 git是赫赫有名的Linux之父Linus Torvalds从2005年起开发的文件版本管理系统,掌控Linux内核这样一个最为重量级的世界产品的Linus为什么要开发这个东西呢?因为Linux系统由全世界的程序员协作维护,对源代码文件的版本控制管理的需求…...

requests post json/data;requests response 接收不同数据

1、requests post json/data 在Python的requests库中,当你发送POST请求时,可以选择使用json参数或data参数来传递数据。这两者之间的主要区别在于它们如何被序列化和发送到服务器。 json参数: 当你使用json参数时,requests库会自…...

【qt】平面CAD(计算机辅助设计 )项目 上

CAD 一.前言二.界面设计三.提升类四.接受槽函数五.实现图形action1.矩形2.椭圆3.圆形4.三角形5.梯形6.直线7.文本 六.总结 一.前言 用我们上节课刚刚学过的GraphicsView架构来绘制一个可以交互的CAD项目! 效果图: 二.界面设计 添加2个工具栏 需要蔬菜的dd我! 添加action: …...

C++中bool类型的使用细节

C中bool类型的使用细节 ANSIISO C标准添加了一种名叫bool的新类型(对 C来说是新的)。它的名称来源于英国数学家 George Boole,是他开发了逻辑律的数学表示法。在计算中,布尔变量的值可以是true或false。过去,C和C一样,也没有布尔…...

Java 面向对象 -- Java 语言的封装、继承、多态、内部类和 Object 类

大家好,我是栗筝i,这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 007 篇文章,在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验,并希望进…...

【C++】和【预训练模型】实现【机器学习】【图像分类】的终极指南

目录 💗1. 准备工作和环境配置💕 💖安装OpenCV💕 💖安装Dlib💕 下载并编译TensorFlow C API💕 💗2. 下载和配置预训练模型💕 💖2.1 下载预训练的ResNet…...

HTML5 Web SQL数据库:浏览器中的轻量级数据库解决方案

在HTML5时代,Web开发迎来了一系列创新特性,其中之一便是Web SQL数据库。尽管Web SQL标准已被W3C废弃,转而推荐IndexedDB作为替代,但了解Web SQL对于学习Web存储技术的演进历程仍有其价值。本文将详细介绍Web SQL数据库的基本概念、…...

C++ const关键字有多种用法举例

C const关键字有多种用法 可以用来修饰变量、指针、函数参数、成员函数等。可以看到const在C中有多种用法,主要用于保证数据的不可变性,增强代码的安全性和可读性。在实际编程中,根据需要选择适当的const用法,可以有效避免意外修…...

Makefile-快速掌握

引用 本文完全参照大佬的文档写的,写这篇文章只是为了梳理一下知识 https://github.com/marmotedu/geekbang-go/blob/master/makefile/Makefile%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86.md 介绍 Makefile是一个工程文件的编译规则,描述了整个工程的编译…...

定个小目标之刷LeetCode热题(20)

这题与上一题有一点不同,上一题是判断链表是否存在环,这题是寻找入环的第一个节点,有一个规则是这样的,在存在环的情况下,运用快慢指针判断是否有环结束时,把快指针指向头结点,慢指针不变&#…...

短剧分销小程序:影视产业链中的新兴力量

一、引言 在数字化浪潮的推动下,影视产业正迎来一场深刻的变革。短剧分销小程序作为这场变革中的新兴力量,正以其独特的魅力和价值,逐渐在影视产业链中崭露头角。本文将探讨短剧分销小程序在影视产业链中的新兴地位、其带来的变革以及未来的…...