java—爆肝1w字❤只为弄懂抽象类和接口(代码片段)

一朵花花 一朵花花     2022-12-30     574

关键词:

抽象类

定义和语法

包含抽象方法的类,叫做抽象类 需要用abstract修饰这个类

在Java中,一个类如果被 abstract 修饰类称为抽象类,抽象类中被 abstract 修饰的方法称为抽象方法,抽象方法可以没有具体的实现

抽象类中可以包含其他非抽象方法,也可以包含字段,非抽象方法和普通方法的规则是一样的,可以被重写,也可以被子类直接调用

//抽象类
abstract class Shape2
	// 抽象方法
    public abstract void draw();
    //抽象类可以增加属性
    public int a;
    // 抽象类可以增加方法
    public void func()
    

理解抽象类

1.不能实例化对象

/*
abstract class Shape2
  public abstract void draw();

*/

Shape2 shape = new Shape();
编译出错
error:shape 是抽象的,无法实例化

2.抽象方法不能为 private的

抽象方法没有加访问限定符时,默认是public

abstract class Shape2
   private abstract void draw();

编译出错
error:非法的修饰限定符组合:private + abstract

3.抽象方法不能被 fina l和 static 修饰

因为抽象方法要被子类重写

abstract class Shape 
	abstract final void methodA();
	abstract public static void methodB();

   
编译出错
error:非法的修饰限定符组合:final + abstract
      非法的修饰限定符组合:static + abstract

4.抽象类必须被继承

且继承后子类要重写父类中的抽象方法,否则子类也是抽象类,就要使用 abstract修饰

abstract class Shape2
   //如果一个方法没有具体实现,那么这个方法可以是一个抽象方法
   public abstract void draw();
   //一个方法是抽象方法,那么存放它的类一定要声明成 抽象类

class Cycle extends Shape2
   @Override
   public void draw() 
       System.out.println("画一个⚪");
  

//如果一个类继承了抽象类,那么该类一定要实现抽象类里的方法
class Triangle extends Shape2
   @Override
   public void draw() 
       System.out.println("画一个▲");
   

class Flower extends Shape2
   @Override
   public void draw() 
       System.out.println("画一个❀");
   

作用

抽象类存在最大的意义:就是为了被继承
抽象类本身不能被实例化,要想使用,必须创建该抽象类的子类,然后让子类重写抽象类中的抽象方法

抽象类总结:

  1. 抽象类不可以被实例化,即 不能:Shape2 shape = new Shape();
  2. 类内的数据成员和普通类没有区别,即:抽象类内部可以包含普通方法和属性,甚至构造方法
    唯一的就是其成员不能被实例化
  3. 抽象类生来就是被继承的
  4. 若一个类继承了抽象类,那么该类必须重写抽象类当中的抽象方法
  5. 抽象类 / 抽象方法一定不能被 final 修饰
  6. 一个方法是抽象方法,那么存放它的类一定要声明成 抽象类
    抽象类中不一定包含抽象方法,但是有抽象方法的类一定是抽象类
  7. 当抽象类A 继承抽象类B,A可以不重写B的方法,但一旦A再被继承,那么一定还要重写抽象方法
  8. 抽象方法一定不能被 final 和 static 修饰

接口

概念

在现实生活中,接口的例子很多,比如电脑的USB接口,电源插座…

电脑的USB口上,可以插:U盘、鼠标、键盘…所有符合USB协议的设备
电源插座插孔上,可以插:电脑、电视机、电饭煲…所有符合规范的设备

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

接口是抽象类的更进一步,抽象类中还可以包含非抽象方法,和字段,而接口中包含的方法都是抽象方法,字段只能包含静态常量

接口特性

1.接口当中的方法,都是抽象方法
2.接口中可以有具体实现的方法,需要用default修饰,JDK1.8 加入的

.

3.接口中定义的成员变量,默认是常量

.

4.接口是不可以用来实例化的

.

5.接口和类的关系:implements

一旦一个类实现了接口,那么一定要重写接口当中的方法
.

6.可解决Java单继承问题

.

7.可发生向上转型

.

前提是:把一个对象赋值给接口类型之前,一定要保证这个类实现了这个接口
例如下边代码:Cycle实现了Shape,故可以发生向上转型
.
接口中的方法是不能在接口中实现的,只能由实现接口的类来实现
.

注意事项:

  • 使用 interface 定义一个接口
  • 接口中的方法一定是抽象方法,故 abstract 可以省略
    接口中的方法一定格式 public,故 public 可以省略
  • 类使用 implements 继承接口,此处的含义是"实现"
  • 接口不能被实例化
  • 只要这个类实现了该接口,那么就可发生向上转型
  • 一旦一个类实现了接口,那么一定要重写接口当中的方法
    接口中的方法是不能在接口中实现的,只能由实现接口的类来实现

实现多个接口

有时,我们需要一个类同时继承多个父类,在有些编程语言中可通过多继承方式来实现,但Java中,只支持"单继承"一个类只能 extends 一个父类,但可同时实现多个接口,也能达到类似多继承的效果

Java 面向对象编程中最常见的用法:一个类继承一个父类,同时实现多种接口

代码理解:

class Animal
    protected String name;
    //提供构造方法
    public Animal(String name)
        this.name = name;
    

//定义接口
interface IFlying
    void fly();

interface IRunning
    void run();

interface ISwimming
    void swim();

//猫
// 先 extends 后 implements
class Cat extends Animal implements IRunning 
    public Cat(String name) 
        super(name);
    
    @Override
    public void run() 
        System.out.println(this.name + "正在用四条腿跑");
    

//鱼
class Fish extends Animal implements ISwimming 
    public Fish(String name) 
        super(name);
    
    @Override
    public void swim() 
        System.out.println(this.name + "正在用尾巴游泳");
    

//青蛙
class Frog extends Animal implements IRunning, ISwimming 
    public Frog(String name) 
        super(name);
    
    @Override
    public void run() 
        System.out.println(this.name + "正在往前跳");
    
    @Override
    public void swim() 
        System.out.println(this.name + "正在蹬腿游泳");
    

//鸭子
class Duck extends Animal implements IRunning, ISwimming,IFlying
    public Duck(String name)
        super(name);
    
    @Override
    public void fly() 
        System.out.println(this.name + "正在飞飞飞");
    
    @Override
    public void run() 
        System.out.println(this.name + "正在跑啊跑");
    
    @Override
    public void swim() 
        System.out.println(this.name + "正在游啊泳");
    

猫🐱:具有跑能力
鱼🐟:具有游泳能力
青蛙🐸:具有跑、游泳能力
鸭子🦆:具有飞、跑、游泳能力
.
可见,把 run,swim,fly 写在Animal里是不合适的,因为不是每一种动物都具备这些能力

接口主要是对方法的一个抽象,使人时刻牢记多态的好处,让程序猿忘记类型,有了接口之后, 类的使用者就不必关注具体类型,而只关注某个类是否具备某种能力

再看一个例子:

//机器人
class Robot implements IRunning
    @Override
    public void run() 
        System.out.println("我是机器人,看谁跑得快!");
    


public class InterfaceDemo2 
    public static void walk(IRunning running) 
        System.out.println("dudududdududu");
        running.run();
    
    public static void main(String[] args) 
        IRunning iRunning = new Robot();
        //iRunning.run();
        walk(iRunning);
    

输出结果:


在上述 walk 方法内部,我们并不关注到底是哪种动物,只要参数是会跑的就可以,甚至参数可以不是 “动物”,只要会跑即可

接口使用实例

给一个数组排序,直接使用Array.sort即可

public static void main(String[] args) 
   int[] array = 8,6,2,3,4;
   Arrays.sort(array);
   System.out.println(Arrays.toString(array));

假设给定一个学生类 Student

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

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

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

再创建一个学生数组,对这个数组中的元素进行排序

public static void main(String[] args) 
    Student student1 = new Student("花",18,100);
    Student student2 = new Student("A",20,95);
    Student student3 = new Student("B",23,88);
    
    Student[] students = new Student[3];
    students[0] = student1;
    students[1] = student2;
    students[2] = student3;
    Arrays.sort(students);
    System.out.println(Arrays.toString(students));

思考:如果使用 Array.sort 方法能否成功对 student 数组排序?

显然,是不可以的 ,类型转换异常


普通数组,是可以使用 sort 方法进行比较数组成员的,但上述比较的是两个学生对象,就不能直接进行比较了,需要我们实现 Comparable 接口,并实现其中的 compareTo 方法

鼠标放在 implements 后按 Alt + Enter


选择 Implement methods


选定之后,会出现如下代码,只需自己重新实现即可


以年龄比较为例:

class Student implements Comparable<Student> 
    public String name;
    public int age;
    public int score;
    
    public Student(String name,int age,int score)
        this.name = name;
        this.age = age;
        this.score = score;
    
    
    @Override
    public int compareTo(Student o) 
        if (this.age > o.age)
            return 1;
        
        else if(this.age < o.age)
            return -1;
        
        else
            return 0;
        
    

public static void main(String[] args) 
    Student student1 = new Student("花",18,100);
    Student student2 = new Student("A",20,95);
    Student student3 = new Student("B",17,88);
    if(student1.compareTo(student2) < 0) 
        System.out.println("student1的年龄 < student2的年龄");
    

这样便可以根据年龄对 Student 进行比较了

此时,再加上 sort 方法,也可实现

public static void main(String[] args) 
    Student student1 = new Student("花",18,100);
    Student student2 = new Student("A",20,95);
    Student student3 = new Student("B",17,88);

    Student[] students = new Student[3];
    students[0] = student1;
    students[1] = student2;
    students[2] = student3;
    Arrays.sort(students);
    System.out.println(Arrays.toString(students));

会发现输出结果,是以年龄由小到大排列的


在 sort 方法中会自动调用 compareTo 方法,compareTo 的参数是 Object,其实传入的就是 Student 类型的对象
自定义类型要可比较,必须实现 comparable 或 comparator 接口

Clonable 接口和深拷贝

Clonable 是 Java 内置的一个接口
Object 类中存在一个 clone 方法,调用这个方法可以创建一个对象的 “拷贝”,但是要想合法调用 clone 方法,必须要先实现 Clonable 接口,否则就会抛出 CloneNotSupportedException 异常

数组的拷贝:

public static void main(String[] args) 
   	int[] array = 8,5,2,7,4,6,9;
   	int[] array2 = array.clone();
    array2[0] = 66;
    System.out.println(Arrays.toString(array));
    System.out.println(Arrays.toString(array2));

由输出结果,可得,上述拷贝为深拷贝

理解浅拷贝:
两个引用同时指向一个对象
通过array2[0] ,把person里的某一个数据修改了,那么array[0]去访问这个数据时,也被修改了!


要想达到深拷贝,不仅要克隆数组本身,还要把对象也克隆一份


举例:


而上述的 array 可使用 clone 方法,由于 array 的父类是 object,即相当于 array 是默认继承于 object,故 array就有clone方法
当前的person也是默认继承于object,但 person 是自定义类型,不能直接使用 clone 方法

若想克隆自定义类型:

1.实现接口 Cloneable

class Person implements Cloneable 
    public int age;

但会发现,Cloneable 是一个空接口


空接口 也叫做:标记接口
含义:只要一个类实现了这个接口,那么就标记这个类是可以进行clone的

2.重写 clone 方法,默认的即可

class Person implements Cloneable 
    public int age;

    @Override
    protected Object clone() throws CloneNotSupportedException 
        return super.clone();
    

此时person就拥有了clone方法

选中之后会有报错,鼠标放在clone后,按Alt + Enter,选异常(此处随便选一个,后面会详细讲解异常)


再次报错!!!
分析:clone 方法的返回值是 object,因此需要进行强制转换


此时就可以验证深拷贝了:

public static void main(String[] args) throws CloneNotSupportedException 
    Person person1 = new Person();
    Person person2 = (Person) person1.clone();
    System.out.println(person1.age);
    System.out.println(person2.age);
    System.out.println("=======修改========");
    person2.age = 52;
    System.out.println(person1.age);
    System.out.println(person2.age);

输出结果:


可以发现,拷贝后,没有发生改变,考虑 age是简单类型的原因,

再新写一个 Money类
Cloneable 拷贝出的对象是一份 “浅拷贝”

class Money
    double money = 13.14;

class Person implements Cloneable 
    public int age;
    Money m = new Money();

    @Override
    protected Object clone() throws CloneNotSupportedException 
        return super.clone();
    


验证浅拷贝:

public static void main(String[] args) throws CloneNotSupportedException 查看详情  

java抽象类和接口4000+字深度剖析(代码片段)

...藏🧑‍🚀码云仓库:补集王子的代码仓库Java抽象类和接口1.抽象类1.1抽象类概念1.2抽象类语法1.3抽象类特性1.3.1抽象类不能直接实例化对象1.3. 查看详情

抽象的基础类和接口(代码片段)

设计程序时,我们经常都希望基础类只为自己的衍生类提供一个接口。也就是说,我们不想其他任何人实际创建基础类的一个对象,只对上溯造型成它,以便使用它们的接口。为达到这个目的,需要把那个类变成“抽象”的——... 查看详情

java基础5:抽象类和接口(代码片段)

本节主要介绍了抽象类和接口的特性和使用方法。1.抽象类一般会实现一部分操作,并且留一些抽象方法让子类自己实现,比如Stringbuffer和Stringbuilder的父类abstractStringbuilder.2.接口一般指一种规定,比如一个map接口中,可能需要实... 查看详情

接口类和抽象类(代码片段)

抽象类和接口类首先需要明确的是接口类和抽象类是由java语言中发展来的概念,它是java中的一种设计规范或方法。Python提供了对抽象类的支持借助于abc模块Python中可以沿用接口类的概念编程但是Python不提供具体的实现方式,也... 查看详情

java--多态,抽象类和接口(代码片段)

一、抽象类1、抽象类定义在class前添加abstract关键字publicabstractclassAbstractClass2、抽象类是无法实例化的,无法创建对象的,所以抽象类是用来被子类继承的3、final和abstract不能联合使用,这两个关键字是对立的4、抽象... 查看详情

java中抽象类和接口的区别?(代码片段)

什么是抽象类?抽象类是对具体概念的抽象抽象类本质是为了继承只能被public或默认修饰行为层面抽象出来抽象方法抽象类的注意事项抽象类不可以被直接实例化抽象类中可以存在构造方法抽象类可以存在普通方法抽象方法的注... 查看详情

抽象类和接口(代码片段)

在Java中,抽象类接口是面向对象的重要体现。抽象类抽象类基于继承的概念。用abstrac关键字修饰,抽象类定义了一组抽象的方法,抽象方法的具体实现由子类来完成。抽象方法的声明:abstractvoidprint();抽象方法也是用abstract来修... 查看详情

java基础5:抽象类和接口

本文主要介绍了抽象类和接口的特性和使用方法。具体代码在我的GitHub中可以找到https://github.com/h2pl/MyTech文章首发于我的个人博客:https://h2pl.github.io/2018/04/24/javase51抽象类一般会实现一部分操作,并且留一些抽象方法让子类自己... 查看详情

day21接口类和抽象类,隔离原则,开放封闭原则,多态(代码片段)

一、接口类和抽象类:#抽象类和接口类#java编程原则和设计模式#设计模式程序设计具有里程碑意义的设计方式从java中演变出来的#单例模式#一个类只有一个实例#算法导论计算的方法时间和空间的问题权威通用#java#面向对象#java... 查看详情

java抽象类和接口

interfaceIo{   //接口,默认publicvoidspeak();}abstractclassA{//抽象类publicvoidshow(){System.out.println("Helloworld");    //普通方法}abstractvoidshowTime();    //抽象方法}publicclassTestimplementsIo{    //实现接口public 查看详情

java基础抽象类和接口

深入理解Java的接口和抽象类  对于面向对象编程来说,抽象是它的一大特征之一。在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类。这两者有太多相似的地方,又有太多不同的地方。很多人在初学的时候会以为它... 查看详情

java抽象类和接口

**********************第九章抽象类和接口************************** **************************抽象类**************************一.why什么时候想到使用抽象类需求:矩形、三角形、圆形方法:1.求周长2.求面积3.说出我有几条边4.简单的介绍我自己打印... 查看详情

java中的抽象类和接口(代码片段)

目录一、什么是抽象类抽象类在实现多态中的意义 二、接口是什么 通过接口实现多态三、抽象类和接口的区别 各位铁汁们大家好呀😊!😎今天让我们继续学习java,看看java中的抽象类和接口到底是什么🤔... 查看详情

java抽象类和接口

***********************体会接口的好处*******************************一.可维护、可扩展面向接口编程接口:父类型面向父类编程 二.解耦高内聚、低耦合耦合:类和类之间的关系...只要类和类之间有四种关系就是耦合(关联、继承、实现、... 查看详情

[转]java抽象类和接口

很多常见的面试题都会出诸如抽象类和接口有什么区别,什么情况下会使用抽象类和什么情况你会使用接口这样的问题。本文我们将仔细讨论这些话题。在讨论它们之间的不同点之前,我们先看看抽象类、接口各自的特性。抽象... 查看详情

java中抽象类和接口的异同点(代码片段)

前言本文简单介绍抽象类,接口以及它们的异同点,另附简单的代码举例。一、抽象类是什么?在Java语言中使用abstractclass来定义抽象类。抽象类是不能被实例化的,即不能用new关键字来实例化对象。包含抽象方... 查看详情

java抽象类和接口

1Java抽象类在了解抽象类之前,先来了解一下抽象方法。抽象方法:一个被声明为abstract而没有具体实现的方法称为抽象方法。abstractvoidtest();//nobodyandabstract  抽象类:如果一个类含有抽象方法,则称这个类为抽象类,抽象类必... 查看详情