JAVA——接口和抽象类的使用

目录

一、抽象类

1.概述

(1)由来

(2)定义

2.abstract使用格式

(1)抽象方法

(2)抽象类

(3)抽象的使用

3.注意事项

二、接口

1.概述

2.定义格式

(1)含有抽象方法

(2)含有默认方法和静态方法

(3)含有私有方法和私有静态方法

3.基本的实现

(1)实现的概述

(2)抽象方法的使用

(3)默认方法的使用

(4)静态方法的使用

(5)私有方法的使用

4.接口的多实现

(1)抽象方法

(2)默认方法

(3)静态方法

(4)优先级的问题

5.接口的多继承

6.其他成员特点

三、接口和抽象类的区别


一、抽象类

1.概述

(1)由来

        父类中的方法,被它的子类们重写,子类各自的实现都不尽相同。那么父类的方法声明和方法主体,只有声明还有 意义,而方法主体则没有存在的意义了。我们把没有方法主体的方法称为抽象方法。Java语法规定,包含抽象方法 的类就是抽象类。

(2)定义

抽象方法 : 没有方法体的方法。

抽象类:包含抽象方法的类。

2.abstract使用格式

(1)抽象方法

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

修饰符 abstract 返回值类型 方法名 (参数列表);

代码举例:

public abstract void run();

(2)抽象类

        如果一个类包含抽象方法,那么该类必须是抽象类。

定义格式:

abstract class 类名字 { 
}

代码举例:

public abstract class Animal { 
    public abstract void run(); 
}

(3)抽象的使用

        抽象方法: 就是在方法上加abstract关键字,然后去掉大括号,直接分号结束。
        抽象类:  抽象方法所在的类,必须的是抽象类才行,  在class前加一个abstract关键字。

抽象类和抽象方法的使用:

a.不能直接new抽象类对象。

b.必须用一个子类来继承抽象父类。

c.继承的子类必须得重写抽象类中所有的抽象方法,如果不重写,那么请把自己也定义成为一个抽象类。

        继承抽象类的子类必须重写父类所有的抽象方法。否则,该子类也必须声明为抽象类。最终,必须有子类实现该父类的抽象方法,否则,从最初的父类到最终的子类都不能创建对象,失去意义。代码举例:

public abstract class Animal {

    //抽象方法.
    public abstract void  eat();
}



public  class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼....");
    }
}

public class Test {

    public static void main(String[] args) {
        Cat  cat = new  Cat();
        cat.eat();
    }
}

此时的方法重写,是子类对父类抽象方法的完成实现,我们将这种方法重写的操作,也叫做实现方法。  

3.注意事项

a.抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。

b.抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。

c.抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。

d.抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类。

二、接口

1.概述

        接口,是Java语言中一种引用类型,是方法的集合,如果说类的内部封装了成员变量、构造方法和成员方法,那么接口的内部主要就是封装了方法,包含抽象方法(JDK 7及以前),默认方法和静态方法(JDK 8),私有方法(JDK 9)。

        接口的定义,它与定义类方式相似,但是使用interface关键字。它也会编译成为关键字,但一定要明确它并不是类,而是另外一种引用数据类型。

引用数据类型:数组,类,接口。

接口的使用,它不能创建对象,但是可以被实现(implements,类似于被继承).一个实现接口的类(可以看做是接口的子类),需要实现接口中所有的抽象方法,创建该类对象,就可以调用方法了,否则它必须是一个抽象类。

2.定义格式

public interface 接口名称 {
    // 抽象方法
    // 默认方法
    // 静态方法
    // 私有方法
}

(1)含有抽象方法

抽象方法:使用abstract关键字修饰,可以省略,没有方法体。该方法供子类实现使用。

代码如下:

public interface InterFaceName { 
    public abstract void method();
}

(2)含有默认方法和静态方法

默认方法:使用default修饰,不可省略,供子类调用或者子类重写。

静态方法:使用static修饰,供接口直接调用。

代码如下:

public interface InterFaceName {
    public default void method() {
    // 执行语句
    }
    public static void method2() {
    // 执行语句
    }
}

(3)含有私有方法和私有静态方法

私有方法:使用private修饰,供接口中的默认方法或者静态方法调用。

代码如下:

public interface InterFaceName { 
    private void method() {
    	// 执行语句
    }
}

3.基本的实现

(1)实现的概述

        类与接口的关系为实现关系,即类实现接口,该类可以称为接口的实现类,也可以称为接口的子类。实现的动作类似继承,格式相仿,只是关键字不同,实现使用implements关键字。

非抽象子类实现接口:

  • 必须重写接口中所有抽象方法。

  • 继承了接口的默认方法,即可以直接调用,也可以重写。

实现格式:

class 类名 implements 接口名 {
// 重写接口中抽象方法【必须】
// 重写接口中默认方法【可选】
}

(2)抽象方法的使用

        在jdk的任意版本中,都可以定义抽象方法,格式如下:

   public abstract 返回值类型  方法名(参数列表)

必须全部实现,代码如下:

定义接口:

public interface LiveAble {

    public abstract void eat();

    public abstract void sleep();

}

定义实现类:

public class Animal implements LiveAble {
    @Override
    public void eat() {
    	System.out.println("吃东西");
    }

    @Override
    public void sleep() {
    	System.out.println("晚上睡");
    }
}

定义测试类:

public class Test {
    public static void main(String[] args) {
        // 创建子类对象
        Animal a = new Animal();
        // 调用实现后的方法
        a.eat();
        a.sleep();
    }
}

 注意事项:

a.接口当中的抽象方法,修饰符必须有关键字,public abstract  没有的话系统会给补全。

b.也可以省略 ,public abstract。

c.方法的三要素和可以随便定义.。

d.如果实现类没有覆盖重写接口中的所有的抽象方法,那么这个实现类必须是抽象类。

(3)默认方法的使用

        从JDK1.8开始, 接口里允许定义默认方法,格式如下:

public default 返回值类型  方法名称(参数列表){
       方法体
  }

接口中的默认方法两种使用:

a. 接口中的默认方法,可以通过该接口的实现类来进行调用。

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

可以继承,可以重写,二选一,但是只能通过实现类的对象来调用。

继承默认方法,代码如下:

定义接口:

public interface MyInterfaceDefault {

    //抽象方法
    public abstract void methodAbs();
  
    //创建一个默认方法
    public default void methodDefault(){
        System.out.println("默认方法...");
    }
}

定义实现类:

public class MyInterfaceDefaultA implements MyInterfaceDefault {
    @Override
    public void methodAbs() {
        System.out.println("AAAA");
    }

    @Override
    public  void methodDefault(){
        System.out.println("A实现类默认方法");
    }
}

定义测试类:

public class Test {

    public static void main(String[] args) {
      
        MyInterfaceDefaultA  a = new MyInterfaceDefaultA();
        a.methodAbs();//AAAA
        a.methodDefault();
    }
}

重写默认方法,代码如下:

定义接口:

public interface MyInterfaceDefault {
     //创建一个默认方法
    public default void methodDefault(){
        System.out.println("默认方法...");
    }
}

定义实现类:

public class Animal implements MyInterfaceDefault {
    @Override
    public void methodDefault() { 
        System.out.println("自由自在的飞");
    }
}

定义测试类:

public class Test {
    public static void main(String[] args) {
        // 创建子类对象
        Animal a = new Animal();
        // 调用重写方法
        a.methodDefault();
    }
}

 (4)静态方法的使用

        从JDK1.8开始,接口中允许定义静态方法,格式如下:

 public static 返回值类型  方法名(参数){
      方法体
   }

静态与.class 文件相关,只能使用接口名调用,不可以通过实现类的类名或者实现类的对象调用,代码如下:

定义接口:

public interface MyInterfaceStatic {

    public static void methodStatic(){
        System.out.println("这是接口的静态方法.....");
    }
}

定义实现类:

public class MyInterfaceStaticImpl implements MyInterfaceStatic {
    // 无法重写静态方法
}

定义测试类:

public class Test {

    public static void main(String[] args) {
        MyInterfaceStatic.methodStatic();
    }
}

tips:不能通过接口实现类的对象来调用接口中的静态方法,正确方式为通过接口名称.直接调用静态方法,格式为接口名称.静态方法。

(5)私有方法的使用

        从jdk9开始,接口当中允许定义私有方法其格式如下:

a.普通的私有方法,解决代码重复性的问题。

private  返回值类型  方法名 (参数列表){
      方法体
   }

b.静态的私有方法,也可以解决多个静态代码直接重复的代码问题。

private  static 返回值类型  方法名(参数列表){
        方法体.
     }

私有方法:只有默认方法可以调用。​

私有静态方法:默认方法和静态方法可以调用。

如果一个接口中有多个默认方法,并且方法中有重复的内容,那么可以抽取出来,封装到私有方法中,供默认方法去调用。从设计的角度讲,私有的方法是对默认方法和静态方法的辅助。

public interface MyInterfacePrivateA {

    public default void methodDefault1(){
        System.out.println("默认方法1");
        methodCommon();
    }

    public default   void methodDefault2(){
        System.out.println("默认方法2");
        methodCommon();
    }

    private void methodCommon(){
        System.out.println("AAA");
        System.out.println("BBB");
        System.out.println("CCC");
    }
}

4.接口的多实现

        在继承体系中,一个类只能继承一个父类。而对于接口而言,一个类是可以实现多个接口的,这叫做接口的多实现。并且,一个类能继承一个父类,同时实现多个接口。实现格式:

class 类名 [extends 父类名] implements 接口名1,接口名2,接口名3... {
// 重写接口中抽象方法【必须】
// 重写接口中默认方法【不重名时可选】
}

[ ]: 表示可选操作。

使用接口的时候,需要注意:

a.接口中没有静态代码块和构造方法。

b.一个类的直接父类是唯一的,但是一个类可以实现多个接口。

c.如果实现类所实现的多个接口中,存在重复的抽象方法,那么重写一次即可。

d.如果实现类没有重写所有实现的接口中的抽象方法,那么实现类必须是一个抽象类。

e.如果两个接口中有相同的默认的方法,那么实现类需要覆盖重写该默认方法。

f.一个类中如果直接父类中的方法和接口当中的默认方法产生冲突,优先使用父类当中的方法 。

(1)抽象方法

        接口中,有多个抽象方法时,实现类必须重写所有抽象方法。如果抽象方法有重名的,只需要重写一次。代码如 下:

定义多个接口:

interface A {
	public abstract void showA();
    public abstract void show();
}

interface B {
	public abstract void showB(); 
    public abstract void show();
}

定义实现类:

public class C implements A,B{
	@Override 
    public void showA() { 
        System.out.println("showA"); 
    }
    @Override 
    public void showB() { 
        System.out.println("showB"); 
    }
    @Override 
    public void show() { 
        System.out.println("show"); 
    }
}

(2)默认方法

        接口中,有多个默认方法时,实现类都可继承使用。如果默认方法有重名的,必须重写一次。代码如下:

定义多个接口:

interface A { 
    public default void methodA(){} 
    public default void method(){}
}

interface B { 
    public default void methodB(){}
    public default void method(){}
}

定义实现类:

public class C implements A,B{ 
    @Override 
    public void method() { 
        System.out.println("method"); 
    } 
}

(3)静态方法

        接口中,存在同名的静态方法并不会冲突,原因是只能通过各自接口名访问静态方法。

(4)优先级的问题

        当一个类,既继承一个父类,又实现若干个接口时,父类中的成员方法与接口中的默认方法重名,子类就近选择执 行父类的成员方法。代码如下:

定义接口:

interface A { 
    public default void methodA(){ 
        System.out.println("AAAAAAAAAAAA"); 
    }
}

定义父类:

class B { 
    public void methodA(){ 
        System.out.println("BBBBBBBBBBBB");
    } 
}

定义子类:

class C extends B implements A { 
    // 未重写methodA方法 
}

定义测试类:

public class Test {
    public static void main(String[] args) { 
        C c = new C(); 
        c.methodA();
    } 
}

5.接口的多继承

        一个接口能继承另一个或者多个接口,这和类之间的继承比较相似。接口的继承使用extends关键字,子接口继承父接口的方法。如果父接口中的默认方法有重名的,那么子接口需要重写一次。代码如下:

定义父接口:

interface A { 
    public default void method(){ 
        System.out.println("AAAAA"); 
    } 
}

interface B { 
    public default void method(){
        System.out.println("BBBBB"); 
    }
}

定义子接口:

interface C extends A,B{ 
    @Override 
    public default void method() {
        System.out.println("CCCCC");
    } 
}

tips:

子接口重写默认方法时,default关键字可以保留。

子类重写默认方法时,default关键字不可以保留。

6.其他成员特点

a.接口中,无法定义成员变量,但是可以定义常量,其值不可以改变,默认使用public static final修饰。

b.接口中,没有构造方法,不能创建对象。

c.接口中,没有静态代码块。

三、接口和抽象类的区别

特征接口抽象类
定义一个完全抽象的类型,只包含方法声明,不包含方法实现。一个部分抽象的类型,可以包含抽象方法和非抽象方法。
方法实现所有方法都是抽象的,必须由子类实现。可以包含抽象方法,也可以包含非抽象方法。
继承类可以实现多个接口。类只能继承一个抽象类。
构造函数接口不能有构造函数。抽象类可以有构造函数。
成员变量接口只能包含常量(static final),不能包含变量。抽象类可以包含成员变量。
目的定义契约,规范行为。提供公共代码和抽象行为。
实例化接口不能直接实例化。抽象类也不能直接实例化。
示例Comparable 接口,定义了 compareTo() 方法。Animal 抽象类,定义了 eat() 方法。

小结:
1.在抽象类中可以有非抽象的方法,在接口中只能有抽象方法。

2.使用接口更灵活,可以实现多继承,而抽象类只能单继承。

3.接口更像是一种规范,定义了一个类的行为标准,而抽象类则更像是一个半成品,提供了一些公共代码和抽象行为,需要子类来完成具体实现。

4.接口通常用于定义系统中不同模块之间的交互标准,而抽象类通常用于实现代码复用和抽象行为。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值