Java基础11——抽象类和接口

Java基础11——抽象类和接口

抽象类和抽象方法

区分普通方法和抽象方法

在Java 中,当一个类被 abstract 关键字修饰的时候这个类称为抽象类。当一个类的方法被 abstract 关键字修饰的时候,该方法称为抽象

方法。抽象方法必须定义在抽象类中。当一个方法被定义为抽象方法后,意味着该方法不会有具体的实现,而是在抽象类的子类中通过方法重写进行实现。定义抽象方法的语法格式如下:

[访问修饰符]abstract <返回类型><方法名>([参数列表])abstract 关键字表示该方法被定义为抽象方法。

普通方法和抽象方法相比,主要有下列两点区别:

  • 抽象方法需要用修饰符 abstract 修饰,普通方法不允许
  • 普通方法有方法体,抽象方法没有方法体。

区分普通类和抽象类

在Java中,当一个类被abstract关键字修饰时,该类为抽象类。定义抽象类的方法如下:

    abstract class <类名>{}

abstract关键字表示该类被定义为抽象类。

普通类与抽象类相比,主要有下列两点区别:

  • 抽象类需要用修饰符 abstract 修饰,普通类不允许
  • 普通类可以被实例化,抽象类不可以被实例化。
public abstract class Person {//属性private String name = "无名氏";private int age = 100;private int weight = 0;//构造方法public Person(String name){this.name = name;}public void print(){System.out.println("我的名字是"+ this.name + ",年龄是" + this.age + ",体重是"+this.weight ".");}
}class Test{public static void main(String[] args) {//Pet pet = new Pet("大黄");//错误示范,因为抽象类不能实例化}
}

定义一个抽象类

当一个类被定义为抽象类时,它可以包含各种类型的成员,包括属性、方法等,其中方法又分为普通方法和抽象方法,下面是抽象类结构的示例:

public abstract class 类名{修饰符 数据类型  变量名;修饰符 abstract 返回值类型 方法名称(参数列表);修饰符 返回值类型 方法名称(参数列表){}
}

提示:

  • abstract 修饰的抽象方法没有方法体
  • private 关键字不能用来修饰抽象方法,否则由于封装导致子类无法重写抽象方法
  • 抽象类不能被之间实例化,但有构造方法
  • 子类如果不是抽象类,则子类必须重写抽象类中的全部抽象方法
  • abstract 修饰符不能和final修饰符一起使用

抽象类和具体类的比较

抽象类和具体类是面向对象编程中的两个重要概念

  • **抽象类: **抽象类是一种不能被实例化的类,它只能被用作其他类的基类。它的目的是为了提供一种基于继承的模板,强制要求子类实现它的抽象方法。抽象类中可能包含一些实现方法,但是也可以只包含抽象方法。

  • 抽象类的主要特点:

    • 不能被实例化
    • 可以包含抽象方法和非抽象方法
    • 子类必须实现抽象方法
    • 抽象类可以包含构造函数。
  • 具体类: 具体类是可以被实例化的类,它可以直接使用,也可以继承自其他类。具体类中必须要实现它的所有方法,不能有未实现的方法。它可以包含属性、方法、构造函数等。

  • 具体类的主要特点:

    • 可以被实例化
    • 必须实现所有方法,可以包含属性、方法、构造函数等。

两者的比较:

  • 抽象类和具体类在定义上的差异:抽象类是一种不能被实例化的类,它只能被用作其他类的基类。具体类则是可以被实例化的类。

  • 抽象类和具体类在实现上的差异:抽象类可以包含抽象方法和非抽象方法,子类必须实现抽象方法; 具体类必须实现它的所有方法,不能有未实现的方法。

  • 抽象类和具体类在使用上的差异:抽象类通常用于定义一些基础的、通用的行为和属性,而具体类则用于实现具体的业务逻辑和行为。

    总的来说,抽象类和具体类是两种不同类型的类,它们的作用和使用场景也不同。

    抽象类用于定义一些通用的行为和属性,并强制子类实现抽象方法,具体类则用于实现具体的业务逻辑和行为。

内部类

内部类是指讲一个类定义在另外一个类的内部,称为内部类。

成员类可以解决类单继承问题

public class AbstractDemo {//外部类private  static   int a =0;private  int b =3;public  void a(){
//        Abstr abstr = new Abstr();new Abstr().test();Abstr.abc();}static  class  Abstr {private int aa =3;private static int bb=2;public void test(){int a = 5;System.out.println(aa);aa=2;System.out.println(aa);System.out.println(bb);Abstr.bb=4;System.out.println(bb);System.out.println(AbstractDemo.a);AbstractDemo.a=5;System.out.println(AbstractDemo.a);System.out.println(a);}public static void abc(){System.out.println("a");Abstr.bb=3;new Abstr().aa=1;}}
class Abstra{//内部类private  static  int b =3;private  int aa =2;public  void test1(){int b =2;System.out.println(b);//当前类的对象AbstractDemo.this.b=5;//外部类的对象System.out.println(AbstractDemo.this.b);}}public static void main(String[] args) {AbstractDemo.Abstr ab = new AbstractDemo.Abstr();ab.test();Abstr.abc();AbstractDemo.Abstra abs = new Abstractemo().new Abstra();  //        abs.test1();}
}  

内部类

在一个类中声明的类称为内部类. 内部类是一个嵌套类.

内部类包含以下几种:

  • 成员类。在类的里面直接声明的类
  • 局部类。声明在一个块中, 当 main 方法调用结束,就销毁
  • 匿名类。

匿名类

之前定义的类都是命名类,也就是类都有明确的名称。匿名类是指没有明确名称的类。

public abstract class AbstractDemo2 {public static void test(){System.out.println("哈哈哈");}public abstract void play();
}public TestAbstract() {}
public static void main(String[] args) {AbstractDemo2 stu = new AbstractDemo2() {@Overridepublic void play() {System.out.println("发发发");}};stu.play();
}
}

Notes:

  • static 成员类, 使用 类名. 调用. 使用 new 外部类.内部类();
  • 实例成员类, 使用外部类的对象来调用. 使用 对象.new 内部类();
  • 成员类属于类的成员,所以可以调用外部类的 private 成员
  • 在实例成员类中可以使用 外部类.this 表示外部类对象 (实例成员类是由外部类对象创建的)
  • 成员类中的 this 表示的是成员类
  • 外部类可以直接调用成员类的静态成员,实例成员需要创建成员类的对象来调用
  • 外部类可以访问成员类的 private 成员
  • 类的成员: 字段、方法、成员类/接口
  • 成员类(内部类): 在类的里面声明的类. 可以被继承
  • 外部类的访问修饰符只能是: public / package-access
  • 成员类的访问修饰符可以是所有的访问修饰符
  • 可以使用 final static abstract 等修饰符修饰成员类

接口基本概念

约定好规范,然后按照规范来做。接口就是定义规范。

  • 描述规范的数据类型
  • 只定义规范(不需要实现):提供一种约定,使实现接口的类在形式上保持一致。
  • Java中规范可以用接口interface来表示

抽象类中可以有普通方法,而接口中的方法默认都是抽象的,也可以说接口是一个 ”特殊的 抽象类 “,接口不能被实例化,而且没有构造方法。

接口的格式

public interface 接口名{// 接口成员
}

解析:

  • 定义接口使用interface修饰符

  • 一个接口可以继承其它接口,称为父接口,且接口可以多继承;它会继承父接口中声明的常量和抽象方法

  • 成员列表中的成员变量声明[public][static][final] 数据类型 成员变量名 = 常量;即,接口中的成员变量默认都是public、static、final的,因此,public、static、final 可以省略

  • 成员列表中的成员方法声明[public][abstract] 返回值类型 方法名称(参数列表);即接口中的方法默认都是public、abstract的,因此,public、abstract可以省略

  • 接口中的变量只能是静态常量( static final ) , 所以可以省略 public static final ,静态常量在定义时就要赋值,且不可变。

接口的使用

与抽象类一样,使用接口要通过子类,子类通过implements关键字实现接口。

子类通过 implements 关键字实现接口,实现接口就必须实现(重写)接口中的抽象方法

实现接口的语法格式如下:

[修饰符] 类名 implements 接口名{ //实现方法// 普通方法// 属性} 

​ 解析:

  • 实现接口要用implements关键字
  • 一个类可以实现多个接口,各接口之间用逗号分隔
  • 实现接口的类必须实现接口中定义的所有抽象方法,即使类中不使用某个抽象方法也必须实现它,通常用空方法体实现子类不需要的抽象方法,如果抽象方法有返回值,可返回默认值。
  • 接口的实现类允许包含普通方法
  • 在实现抽象方法时需要指定public权限,否则会产生编译错误
  • 类和类之间叫做继承,用extends
  • 类和接口之间叫做实现implement;

多个接口实现

java 中继承是单继承,使用 extends 关键字;

一个接口实现类可以实现多个接口,使用 implements ,多个接口之间用 , 隔开。
public class Computer implements USBInterface, ChargeInterface{ //定义一个实现类实现多个接口public void play() { // 普通方法System.out.println("play game"); }@Override 
public void charge() { //重写抽象方法System.out.println("充电"); 
}@Override 
public void service() { //重写抽象方法System.out.println("USB接口"); } 
}
一个类可以同时继承和实现接口, extends 要在 implements 之前
public class LenovoComputer extends Computer implements USBInterface, ChargeInterface{}
接口与接口之间是继承关系,使用 extends 关键字。多个接口使用 , 隔开
public interface USBC extends USBInterface,ChargeInterface{ } 

JDK8.0 接口新特性 default 和 static

**default:**在 jdk8.0 中 default 关键字可用于在接口中修饰方法(默认方法), default 修饰的方法可以有具体实现,也只能在接口中出现。 default 修饰的方法可以被重写。

默认方法可以在不破坏已经在使用该接口的所有代码。默认方法有时也称为防御方法(defender method)或 虚拟扩展方法(virtual extension method)

**static:**接口中还可以有 static 修饰的方法,称为静态方法(类方法)。 static 方法必须直接使用 接口名.方法名调用。

从Java 8 开始,接口允许定义默认方法(注意是在接口), 格式:

 public default 返回值 方法名(){方法体}

从Java 8 开始,接口允许定义静态方法。

 public static  返回值 方法名(){方法体}

接口名称。静态方法名(参数列表);

public interface Usb {//接口//接口中的抽象方法public abstract void a();//新添加的默认方法public default void b(){System.out.println("实现接口升级");}//新添加的静态方法public static void c(){System.out.println("实现静态方法");}
}
public class Usbfeng implements Usb{//实现类1@Overridepublic void a() {System.out.println("Usbfeng");}
@Override
public void b(){System.out.println("默认default覆盖写法");//重写默认b()方法完全可以,最后实例化对象调用
}  }
public class Usbshan implements Usb{//实现类二@Overridepublic void a() {System.out.println("Usbshan");}
}

1.接口的默认方法,可以通过接口实现类对象,直接调用

2.接口的默认方法,也可以被接口实现类进行覆盖重写

public class Test {//测试类public static void main(String[] args) {
//创建了实现类对象Usbfeng usbfeng = new Usbfeng();usbfeng.a();//调用抽象方法,实现的是右侧实现类usbfeng.b();//调用默认方法,如果实现类中没有,会向上找接口Usbshan usbshan = new Usbshan();usbshan.a();usbshan.b();//调用moUsb.c();}
}

JDK9 接口新特性 private

我们需要抽取一个共有方法,用来解决多个默认方法之间重复代码的问题,但是这个共有方法不应该让实现类使用,所以私有化

解决方案:

从Java 9开始接口当中允许定义私有方法。

1.普通私有方法,解决多个默认方法之间重复代码的问题。

private 返回值类型 方法名称(参数列表){方法体
}
public interface Typc {//代码重复率高public default void a(){System.out.println("默认方法A");System.out.println("AAA");System.out.println("BBB");System.out.println("CCC");}
public default void b(){System.out.println("默认方法B");System.out.println("AAA");System.out.println("BBB");System.out.println("CCC");
}
}
运用私有化后public interface Typc {//因为被私有化,只有a和b能够使用c,其余的地方无法使用public default void a(){System.out.println("默认方法A");c();}public default void b(){System.out.println("默认方法B");c();}private void c(){System.out.println("AAA");System.out.println("BBB");System.out.println("CCC");}
}
测试public class Testtypec {public static void main(String[] args) {Typcc typcc = new Typcc();typcc.b();typcc.a();}
}输出结果

静态私有方法,解决多个静态方法之间重复代码问题

private static 返回值类型 方法名称 (参数列表){方法体
}
  1. 静态私有方法同理,只有本接口多个静态方法可以使用,其余作用域无法使用。
  2. 在Java9以后出现并使用
  3. JDK9 接口中可以使用 private 修饰方法,供接口中其他方法调用。

抽象类和接口的区别(重点)

特性接口抽象类
组合可以在新类中组合多个接口只能继承一个抽象类
状态只含有静态字段、抽象方法、默认方法、静态方法可以包含字段
默认方法和抽象方法默认方法不需要在子类里实现,它只能引用接口中的方法抽象方法必须在子类里实现
构造器不能有构造器(接口没有构造、不能实例化)有构造、同样不能实例化
访问权限隐式 public可以为 protected 或包访问权限

举例:

@FunctionalInterface
interface IType {void test();
}
class Demo{public static void main(String[] args){// 通常使用 匿名类IType a = new IType(){@Overridepublic void test(){ // 实现}};// lambdaIType b = () ->{// 实现};   

如果lambda中实现只有一句代码则可以省略{}这种写法,java可以根据变量的类型推断出匿名类实现的接口,以及重写的方法。方法的写法上:

  • 如果方法没有参数则使用()表示。

  • 如果有参数,则需要在()写形参列表,在实现中可以使用这些参数。

  • 参数的类型可以省略,可以推断出参数类型

  • 如果方法没有参数则使用()表示。

  • 如果只有一个参数()可以省略。

深克隆和浅克隆

浅克隆

浅克隆指创建一个新对象,并将原始对象的所有非静态字段的值复制到新对象中。如果字段的类型是基本类型,那么会复制其值;如果字段的类型是引用类型,则会复制引用,即新对象和原始对象将引用同一个对象。

深克隆

深克隆是指创建一个新对象,并将原始对象的所有字段新对象中,包括引用类型字段所引用的对象。

简单来说就是浅克隆对象中的引用数据类型字段是同一个引用,深克隆会比浅克隆多克隆一个引用数据类型

protected Person clone() throws CloneNotSupportedException {//        return (Person) super.clone();Person copy = (Person) super.clone();// 将引用数据类型 clone 一份, 再设置Dog copyDog = copy.getDog().clone();copy.dog = copyDog;return copy;
}

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

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

相关文章

leetcode 1921. 消灭怪物的最大数量(每日一题)

最近学习的状态找回很多。慢慢来吧&#xff0c;加油&#xff01; 1921. 消灭怪物的最大数量 你正在玩一款电子游戏&#xff0c;在游戏中你需要保护城市免受怪物侵袭。给你一个 下标从 0 开始 且长度为 n 的整数数组 dist &#xff0c;其中 dist[i] 是第 i 个怪物与城市的 初始…

Linux安装MySQL8.0

又又又又..Linux装MySQL。 删除原有的MySQL 查看安装的mysql信息&#xff1a;rpm -qa|grep -i mysql 删除mysql相关服务&#xff1a;rpm -e --nodeps 查询mysql遗留文件和依赖信息&#xff1a;find / -name mysql 手动删除mysql配置文件&#xff1a;rm -rf /etc/my.cnf 相关…

MySQL锁

MySQL锁 事务事务的隔离级别脏读&#xff0c;不可重复读&#xff0c;幻读 表锁与行锁表锁测试准备测试 行锁测试 读锁与写锁读锁&#xff08;共享锁&#xff09;测试 写锁&#xff08;排他锁&#xff09;测试 元数据锁表级元数据锁表级MDL**&#xff08;Metadata Lock&#xff…

十大排序算法及Java中的排序算法

文章目录 一、简介二、时间复杂度三、非线性时间比较类排序冒泡排序&#xff08;Bubble Sort&#xff09;排序过程代码实现步骤拆解演示复杂度 选择排序&#xff08;Selection Sort&#xff09;排序过程代码实现步骤拆解演示复杂度 插入排序&#xff08;Insertion Sort&#xf…

Ei Scopus检索 | 2024年第三届能源与环境工程国际会议(CFEEE 2024)

会议简介 Brief Introduction 2024年第三届能源与环境工程国际会议(CFEEE 2024) 会议时间&#xff1a;2024年9月1日-3日 召开地点&#xff1a;新西兰奥克兰 大会官网&#xff1a;https://www.cfeee.org/ 2024年第三届能源与环境工程国际会议(CFEEE 2024) 将于2024年12月12日至1…

Struts.xml 配置文件说明

<?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <!--…

【Linux常用命令】

一、防火墙相关 1、查看防火墙状态 systemctl status flrewalld2、如果防火墙是开启状态的&#xff0c;需要关闭 systemctl stop firewalld3、永久行关闭操作&#xff08;禁止开机自启动&#xff09; 因为防火默认是开启状态的&#xff0c;如果只是手动关闭&#xff0c;先次…

elasticsearch集群部署-实操

elasticsearch&#xff08;集群&#xff09; 案例版本&#xff1a;elasticsearch 8.6.2 操作系统&#xff1a;CentOS 7 注意&#xff1a;全程使用普通用户操作。 0、节点信息 节点描述192.168.127.10master192.168.127.11slave…slave02 1、环境配置 1.1 修改文件 /etc/se…

中国大学MOOC地下水污染与防治答案

本文转载自 众课帮 众工号 1、下列哪项不属于有机污染物综合指标&#xff08; &#xff09; A、高锰酸盐指数 B、化学需氧量&#xff08;COD&#xff09; C、浊度 D、总有机碳&#xff08;TOC&#xff09; 答案&#xff1a;浊度 2、饮用水水质指标常说的“两虫”是指( ) A、贾…

【Java】抽奖系统———保姆学习教程

目录 一、抽奖系统介绍 二、代码实现 1、随机生成中奖号码 1.1、中奖号码createNumber方法 1.2、控制判断contains方法 2、用户输入中奖号码 3、判断中奖情况 3.1、判断奖项isWin方法 三、完整代码 一、抽奖系统介绍 抽奖的号码由6个红色球号码和1个蓝色球号码组成。红色…

第24节——react hooks组件传值 - 父子组件之间的传值

一、概念 一句话概括&#xff0c;react hook 父子组件之间通过props进行传值 二、父传子 父组件&#xff1a;在子组件标签上定义属性 子组件&#xff1a;函数组件接收一个props是一个对象&#xff0c;父组件传的属性名就是props对象的key&#xff0c;属性的值就是对应的val…

python实现Flask GET Demo

python代码 from flask import Flask, request, jsonifyapp Flask(__name__)#用/data路径路由 app.route(/data) def get_data():## 以下一行是从URL中获取参数的get方法data request.args.get(data)return jsonify(data data,info "success !",code "200…

十五、垃圾回收相关算法

目录 一、标记阶段&#xff1a;引用计算法对象存活判断引用计算法 二、标记阶段&#xff1a;可达性分析算法三、对象的finalization机制四、MAT和Jprofiler的GC Toots的溯源五、垃圾清除算法之标记-清除算法六、垃圾清除算法之复制算法七、垃圾清除算法之标记-压缩算法八、小结…

智慧园区:AI边缘计算技术与视频监控汇聚平台打造智慧园区解决方案

一、行业趋势与背景 智慧园区是现代城市发展的重要组成部分&#xff0c;通过智能化技术提高园区的运营效率、降低成本、增强环境可持续性等具有重要作用。在智慧园区中&#xff0c;人工智能和视频汇聚技术是重要的前置技术。人工智能技术可以实现对数据的智能化处理和分析&…

时序数据库 TimescaleDB 安装与使用

TimescaleDB 是一个时间序列数据库&#xff0c;建立在 PostgreSQL 之上。然而&#xff0c;不仅如此&#xff0c;它还是时间序列的关系数据库。使用 TimescaleDB 的开发人员将受益于专门构建的时间序列数据库以及经典的关系数据库 (PostgreSQL)&#xff0c;所有这些都具有完整的…

2023/9/13 -- C++/QT

作业&#xff1a; 1> 将之前定义的栈类和队列类都实现成模板类 栈&#xff1a; #include <iostream> #define MAX 40 using namespace std;template <typename T> class Stack{ private:T *data;int top; public:Stack();~Stack();Stack(const Stack &ot…

TouchGFX之缓存位图

位图缓存是专用RAM缓冲区&#xff0c;应用可将位图保存&#xff08;或缓存&#xff09;在其中。 如果缓存了位图&#xff0c;在绘制位图时&#xff0c;TouchGFX将自动使用RAM缓存作为像素来源。位图缓存在许多情况下十分有用。 从RAM读取数据通常比从闪存读取要快&#xff08;特…

Linux下Minio分布式存储安装配置(图文详细)

文章目录 Linux下Minio分布式存储安装配置(图文详细)1 资源准备1.1 创建存储目录1.2 获取Minio Server资源1.3 获取Minio Client资源 2 Minio Server安装配置2.1 切换目录2.2 后台启动2.3 查看进程2.4 控制台测试 3 Minio Client安装配置3.1 切换目录3.2 移动mc脚本3.2 运行mc命…

结构型设计模式

结构型设计模式 结构型设计模式主要总结了一些类或对象组合在一起的经典结构&#xff0c;这些经典的结构可以解决特定应用场景的问题。结构模式包括&#xff1a;代理模式、桥接模式、装饰器模式、适配器模式、门面模式、组合模式、亨元模式。 1. 代理模式 实现方式&#xff…

Vue3后台管理系统Element-plus_侧边栏制作_无限递归

在home.view中添加代码 <template><div><div class"common-layout"><el-container><el-header class"common-header flex-float"><div class"flex"><img class"logo" src"../assets/logo…