Java学习笔记——抽象类和接口

抽象类和接口

1. 抽象类
2. 抽象方法
3. 接口

第一节: 抽象类

1.1 为什么使用抽象类

  • 有些类创建对象没有意义。需要把这个定义为抽象类
    • 1 Animal animal=new Animal();
    • 2 Pet pet=new Pet()
  • 使用abstract修饰类变成抽象类:不能实例化,只能被继承
  • 抽象类的构造方法不能直接使用,只能被子类调用。

1.2 abstract 关键字

关键字:abstract:抽象

可以修饰类:叫做抽象类

可以修饰方法:叫做抽象方法,没有方法体,需要使用分号表示声明结束,抽象方法所在的类必须是抽象类

子类必须重写父类的抽象方法,除非子类也是抽象类

1.3 抽象方法

使用abstract关键字修饰,只表示声明了一个方法,但是没有任何的实现

特点:

1)没有方法体,需要使用分号表示方法声明结束

2)如果一个类中有一个方法是抽象的,那么这个类必须是抽象的

3)抽象方法必须被子类重写,除非子类也是抽象类

1.4 抽象类:

使用abstract关键字修饰

特点:

1)抽象类中可以包含抽象方法,也可以包含普通方法。

2)抽象类中有构造方法,但是不能创建对象,构造方法目的在子类中会被调用。

3)抽象类的存在就是为了被继承,子类必须重写父类的抽象方法,除非子类也是抽象类。

1.5 抽象类和普通类的区别:

1)抽象类需要abstract,而普通类不需要

2)构造方法:都有,但是抽象类不能实例化对象,普通类可以

3)成员方法:抽象类中可以存在抽象的成员方法也可以存在非抽象成员方法,而普通类中只能存在非抽象成员方法

思考:final和abstract是否可以连用?

1)两个关键字修饰方法时,final修饰的方法特点:可以被继承不能被重写;abstract修饰的方法特点:必须被重写;所以这两个关键字不能同时修饰同一个方法

2)两个关键字修饰类时:final修饰的类特点:不能被继承;abstract修饰的类特点:必须被继承;所以这两个关键字不能同时修饰同一个类

综上所述:final和abstract不可以连用

final的类中能否有abstract方法?不能

abstract类中能否有final方法?可以

上机练习1:

编写交通工具类,具有前进run()功能,子类有自行车、小轿车、地铁,重写父类方法,主人有属性name,age属性,方法回家goHome(交通工具),需要使用交通工具,使用抽象类优化程序
TrafficTool
Bicycle
Car
Subway
Master


package com.qf.day12;
/**
 * 编写交通工具类,具有前进run()功能,子类有自行车、小轿车、地铁,重写父类方法,主人有属性name,age属性,方法回家goHome(交通工具),需要使用交通工具,使用抽象类优化程序
TrafficTool
Bicycle
Car
Subway
Master
 * @author wgy
 *
 */
public abstract class TracficTool {
    //品牌
    private String brand;

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }
    public TracficTool() {
        // TODO Auto-generated constructor stub
    }

    public TracficTool(String brand) {
        super();
        this.brand = brand;
    }

    /**
     * 前进方法
     */
    public abstract void run();

}


package com.qf.day12;

public class Bicycle extends TracficTool {

    public Bicycle() {
        // TODO Auto-generated constructor stub
    }



    public Bicycle(String brand) {
        super(brand);
    }



    @Override
    public void run() {
        System.out.println(getBrand()+"的自行车,在行驶...............");
    }
}

package com.qf.day12;

public class Car extends TracficTool{

    public Car() {
        // TODO Auto-generated constructor stub
    }


    public Car(String brand) {
        super(brand);
        // TODO Auto-generated constructor stub
    }


    @Override
    public void run() {
        System.out.println(getBrand()+"轿车正在飞速的前进............");
    }
}

package com.qf.day12;

public class Subway extends TracficTool {
    public Subway() {
        // TODO Auto-generated constructor stub
    }


    public Subway(String brand) {
        super(brand);
        // TODO Auto-generated constructor stub
    }


    @Override
    public void run() {
        System.out.println(getBrand()+"地铁,在高速前进..............");
    }
}

package com.qf.day12;
/**
 * 主人
 * @author wgy
 *
 */
public class Master {
    private String name;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

    public Master() {
        // TODO Auto-generated constructor stub
    }
    public Master(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    //回家

    public void goHome(TracficTool tool) {
        System.out.println(getName()+"下班了,要回家...");
        tool.run();
        System.out.println(getName()+"到家了...");
    }



}


package com.qf.day12;

public class Test {
    public static void main(String[] args) {
        Master zhengshuai=new Master("郑帅", 29);
        Bicycle fenghuang=new Bicycle("凤凰牌");
        Car baoshijie=new Car("保时捷");
        Subway shuaishuai=new Subway("北京地铁");

        zhengshuai.goHome(fenghuang);
        zhengshuai.goHome(baoshijie);
        zhengshuai.goHome(shuaishuai);

    }
}

1.6 static,final,abstract总结

修饰符 修饰对象 规则
static 属性 表示类公共的属性,使用类来调用,推荐使用类调用(类名.属性名)
方法 表示类公共的方法,在静态方法中只能直接调用静态变量或静态方法,不能使用this,super,如果要想调用非静态方法和属性,需要创建对象。
代码块 静态代码块,程序一加载静态代码块就运行,而且只运行一次
final 属性、局部变量 常量,final int i=12;或者final int i;i=12;只能赋值一次。
方法 该方法不能被子类重写,可以被继承。
类 该类不能被继承。
abstract 方法 抽象方法,该方法只有方法声明,没有方法体
构造方法和static方法、final方法不能是抽象的
有该方法的类称为抽象类,类名前必须加abstract
类 抽象类不能被实例化
抽象类可以指向子类对象的引用
抽象类可以有普通方法,可以被子类继承
父类的抽象方法必须在子类中实现,除非子类也是抽象类

第二节: 接口

生活中的接口:USB,插座…

USB:物理:必须满足USB接口的宽度和厚度

内部:需要遵守磁片的个数

插座:首先需要满足插头的个数

满足电压和电流一些规则

2.1 接口的概念

从语法上讲:

接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有方法的实现。

从功能上讲:接口表示一种约定或能力

2.2 使用接口的好处

  • 扩展类的功能,保持对外接口一致
  • 接口实现了多重继承,完成类和任何实现接口子类的通信和交互
  • 降低代码之间的耦合性

2.3 接口的特点:

1)接口不能创建对象,而且接口中没有构造方法;

2)接口中的方法一般都是共有抽象方法:public abstract

3)接口中所有的属性都是共有静态常量属性:public static final

在一个接口中声明方法时,若没有声明访问权限,默认也是public,若没其他修饰默认也是abstract;声明属性时,若没有声明访问权限和静态常量,默认也是public static final

public abstract void fun();
接口中可以使用一下格式声明方法:
void fun();
public static final int a = 9;
int a = 9;

2.4 接口的声明语法

关键字interface:表示一个接口,接口interface和类class是平级关系

接口命名:

如果接口表示一种能力,命名采用:名字+后缀able   ,比如 Serializable   Comparable

如果接口表示一种约定或规范 ,按照命名规范正常命名   USB  , Comparator,CharSequence

语法:
public interface 接口名{
    //接口中的成员:抽象方法和静态常量
}

2.5 接口的实现类

接口与类的关系:implements

语法:

pulbic interface I{
    public abstract void fun();
}

public class Impl implements I {
    public void fun(){}
}

思考:一个类实现某个接口之后,是否可以存在父类?

可以,实现接口和继承类不冲突

注意:1.若一个类有父类同时也实现接口,声明类时,必须先继承再实现接口

        2.一个类可以实现多个接口

语法:

public class Dog extends Animal implements I{
    public void fun(){}
}

2.6 接口的分类:

1)普通接口:在接口中可以声明抽象方法,和静态常量属性

2)常量群接口:在接口中只声明一组静态常量属性

3)标志性接口:在接口中没有抽象方法,也没有静态常量,作用为了标记某个类具有某个功能

2.7 接口和接口的关系:

继承关系:使用关键字extends实现接口与接口的继承关系

接口继承的特点:

1)接口中没有私有成员,所以父类接口中的所有成员都会被子接口继承

2)父子关系中都是接口,所以在子接口中不需要实现任何的抽象方法

3)接口可以多继承

2.7 接口中特殊的方法:

1)jdk1.8之后接口中使用static关键字修饰的方法有方法体

静态方法需要有方法体

2)jdk1.8之后接口中使用default关键字修饰的方法有方法体

2.8 接口的使用:

1.USB接口

public interface USBInterface {
    public void server();
}

public class Fan implements USBInterface {
    public void server() {
        // TODO Auto-generated method stub
        System.out.println("风扇和电脑连接成功,开始工作");
    }
}

public class Mouse implements USBInterface{
    public void server() {
        // TODO Auto-generated method stub
        System.out.println("鼠标和电脑连接成功,开始工作");
    }
}

public class Computer {
    //面向接口编程,而不面向具体的实现
    public USBInterface  usb1;
    public USBInterface  usb2;
    public USBInterface  usb3;

    public void Run(){
        System.out.println("电脑启动成功");
        if(usb1!=null) {
            usb1.service();
        }
        if(usb2!=null) {
            usb2.service();
        }
        if(usb3!=null) {
            usb3.service();
        }
    }
}

2.在一个平台或系统中,如果多个类都需要使用到某些方法(功能),可以将这些方法定义到一个接口中,所有需要这些方法的类,可以实现这个接口,有效地实现解耦。

案例:现有交通工具类Transport类

Transport有三个子类,飞机Plane,车Car,船Ship

Plane有,客机,货机,战斗机

Car有客车,货车,坦克

Ship船有客船,货船,航母

战斗机,坦克,航母都有开火攻击的功能,通过分析,此功能不能来自于父类,所以可以将开火攻击的功能设置在一个接口中

//交通工具类
public class Transport {
    //成员方法
    public void yun(String goods) {
        System.out.println("运输"+goods);
    }
}
//飞机类
public class Plane extends Transport {}
//船类
public class Ship extends Transport {}
//车类
public class Car extends Transport {}
//开火攻击接口
public interface Fire {
    public abstract void fire();//开火攻击方法
}
//航母类:继承Ship,实现Fire
public class Carrer extends Ship implements Fire {
    @Override
    public void fire() {
        // TODO Auto-generated method stub
        System.out.println("xiu~~~");
    }
}
//战斗机:继承Plane,实现Fire
public class FightingPlane extends Plane implements Fire {
    @Override
    public void fire() {
        // TODO Auto-generated method stub
        System.out.println("piupiupiu~~");
    }
}
//坦克类:继承Car,实现Fire
public class Tank extends Car implements Fire {
    @Override
    public void fire() {
        // TODO Auto-generated method stub
        System.out.println("轰轰轰~~~");
    }
}
//测试
public class TestTransport {    
    public static void main(String[] args) {
        Fireable fireable1=new FightPlane();
        Fireable fireable2=new Tank();
        Fireable fireable3=new Carrer();

        fight(fireable1);
        fight(fireable2);
        fight(fireable3);
    }
        //战斗方法
    public static void fight(Fireable fireable) {

        for(int i=0;i<10;i++) {
            fireable.fire();
        }
    }
}

2.9 抽象类和接口区别

语法:

1>抽象类使用abstract,接口使用interface

2>抽象类中可以包含抽象方法,也可以包含非抽象方法,接口中只能包含抽象方法和静态常量,jdk1.8之后接口可以包含静态方法和默认方法。

3>抽象类和接口都不能实例化。

4>抽象类可以包含构造方法,接口中没有构造方法。

功能:

1>抽象类一般用来表示同类事物,接口可以表示不是同类事物。

2>抽象类可以实现代码的重用,也可以约束子类的功能。接口就是约束实现类的功能,降低代码之间的耦合性。

使用场景:

1>程序或模块内部使用抽象类(开发中使用比较少)

2>程序架构或模块之间使用接口(比较多)

总结

1 抽象类:

实例化对象没有意思,所以使用抽象类,

抽象类不能实例化

2 abstract关键字

abstract 修饰类表示抽象类

abstract 修饰方法 抽象方法

4 抽象方法

抽象方法没有方法体

抽象方法被子类重写

包含抽象方法的类一定是抽象类

5 抽象类

抽象类不能实例化对象

抽象类可以包含抽象方法,也可以包含非抽象方法

抽象类的抽象方法必须被子类重写,除非子类也是抽象类

6 static final abstract

final 和 abstract 不能一起使用

static和abstract不能一起使用

7接口 :语法:就是特殊的抽象类

    功能:表示一个约定或能力

    接口好处:
  • 扩展类的功能,保持对外接口一致
  • 接口实现了多重继承,完成类和任何实现接口子类的通信和交互
  • 降低代码之间的耦合性

定义接口

public interface 接口名{

    常量

    抽象方法

}

jdk1.8  静态方法和默认方法

实现接口

class  类名 implements 接口名{

    重写接口中抽象方法

}

一个类可以实现多个接口,只能继承一个类

接口与接口的关系: extends ,多继承

public interface Inter1{

}

public interface Inter2{

}

public interface Inter3 extends Inter1,Inter2{

}

接口案例:

Usb案例  表示接口是一个约定

开火案例  表示接口是一个能力

面试题

接口和抽象类有什么区别?

猜你喜欢

转载自blog.csdn.net/lyf1997115/article/details/81535815