Java抽象类和接口基础整理

23 篇文章 0 订阅

一.抽象类

1.定义

抽象类 = 普通类 + 抽象方法
抽象方法 = 声明却未实现的方法(没有方法体)

注意:
(1)没有方法体的方法不一定都是抽象方法哦,还有可能是本地方法;
(2)所有抽象方法要求使用abstract关键字来定义;抽象方法所在的类也必须使用abstract关键字来定义;
(3)抽象类中包含抽象方法,而抽象方法不包含方法体,即没有具体实现。因此抽象类不能直接产生实例化对象;

下面来看一个抽象类的例子:

//抽象水果类
abstract class Fruit{
   private String name;//属性,水果名

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
    public abstract void getFruitInfo();//抽象方法
}

其实说到这里呢,我们会很发现,抽象类的最大特点是什么呢?就是假如说我们有很多水果类,苹果、芒果、火龙果...,它们都有水果名这个属性,那么都可以通过继承抽象水果类来获得父类的属性,也可以在此基础上扩展自己的特性;

来,看一个芒果

class mango extends Fruit{

    @Override
    public void getFruitInfo() {
        System.out.println("Hello,我是芒小果");
    }
}

看,抽象类是不是很棒呢。但是,Java中的继承是单继承哦,下面这种情况是不可以的。

2.抽象类使用原则

(1)所有抽象类必须有子类;
(2)抽象类的子类必须覆写抽象类的所有抽象方法(子类不是抽象类),方法覆写要注意权限问题;
(3)抽象类的对象可以通过对象多态性利用子类为其实例化;
(4)private和abstract不能一起同时使用;

呐,一个经典的例子(在我心里是经典哦):

abstract class Person{
    private String name;//属性

    //普通方法
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

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

class Student extends Person{

    @Override
    public void getPersonInfo() {
        System.out.println("I'm a student");
    }
}
public class Test {
    public static void main(String[] args) {
        Person person = new Student();//向上转型
        person.getPersonInfo();//子类覆写的方法
    }
}

输出:

经典吧,哈哈哈,对,我就是一个小学生

3.抽象类的相关规定

(1)抽象类只是比普通类多了一些抽象方法而已;
抽象类中也有构造方法哦,并且子类也照样遵循对象实例化流程。实例化子类时一定先调用父类构造方法。

栗子:在抽象类中定义构造方法

/**
 * @Author:Star
 * @Date:Created in 15:55 2019/10/14
 * @Description:
 */
abstract class Person{
    private String name;//属性

    public Person() {//构造方法
        System.out.println("***Person***");
    }

    //普通方法
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

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

class Student extends Person{

    public Student() {//构造方法
        System.out.println("###Student###");
    }

    @Override
    public void getPersonInfo() {
        System.out.println("I'm a student");
    }
}
public class Test {
    public static void main(String[] args) {
        new Student();
    }
}

输出:

另外,补充一点点,如果父类没有无参构造,那么子类构造必须使用super明确指出使用父类哪个构造方法。

栗子:

/**
 * @Author:Star
 * @Date:Created in 16:22 2019/10/14
 * @Description:
 */
abstract class A{

    public A(){//3.调用父类构造
        this.print();//4.调用被子类覆写的方法
    }

    public abstract void print();
}

class B extends A{
    private int num = 100;

    public B(int num){//2.调用子类实例化对象
        super();//3.隐含的一行语句,实际要先调用父类构造
        this.num = num;//7.为类中属性初始化
    }

    @Override
    public void print() {//5.此时子类对象的属性还没有被初始化
        System.out.println(this.num);//6.对应其数据类型的默认值
    }
}
public class Test01 {
    public static void main(String[] args) {
        new B(30);//1.实例化子类对象
    }
}

程序的执行顺序就是按照1,2,...,7来执行的,所以要注意哦,即输出为0(对象属性对应数据类型的默认值);

输出:

(2)抽象类可以不定义任何抽象方法,但此时仍然无法直接实例化对象;

(3)final与abstract不能同时出现;private与abstract也不能同时出现;
抽象类一定不能使用final声明,因为使用final声明的类不允许有子类;而抽象类必须有子类;相应的,抽象方法也不能使用private定义,因为抽象方法必须要能被覆写。

(4)抽象类也分为外部抽象类与内部抽象类。内部抽象类中也可以使用static定义来描述外部抽象类;
内部抽象类的抽象方法与外部抽象类的抽象方法无关。
当前直接继承哪个抽象类,就覆写其抽象方法(若直接继承外部抽象类,则只需要覆写外部抽象类的所有抽象方法即可

栗子:内部抽象类

abstract class A{
    public abstract void printA();
    abstract class B{
        public abstract void printB();
    }
}
class X extends A{
    public void printA(){}
    class Y extends B{
        public void printB(){}
    }
}

如果在外部抽象类中使用了static那就是语法错误,但是内部抽象类允许使用static;

栗子:使用了static的内部抽象类

abstract class A{
    public abstract void printA();
    static abstract class B{
        public abstract void printB();
    }
}
class X extends A,B{
    public void printB(){}
}

二.接口

1.定义

 接口 = 抽象方法 + 全局变量(JDK8以前)

栗子:接口定义

interface IFruit{
    public static final String name = "水果";//全局变量
    public abstract void print();//抽象方法
}

注意:

(1)接口优先原则;即可使用接口又可使用抽象类时,优先考虑使用接口
(2)使用interface定义接口,为了区分接口,在所有接口前面追加字母I;
(3)子类实现接口,使用implements关键字,并且子类可以同时实现多个接口(接口多继承);
(4)子类必须覆写所有抽象方法。子类命名一般使用Impl结尾;
(5)多个接口若有共同子类,可以通过子类进行相互转换(父接口之间的相互转换)-new在哪

栗子:子类实现接口和父类接口之间的转换

/**
 * @Author:Star
 * @Date:Created in 17:18 2019/10/14
 * @Description:
 */

interface IFruit{
    public static final String name = "水果";//全局变量
    public abstract void print();//抽象方法
}

interface IApple{
    public abstract String getApple();
}

class bigAppleImpl implements IFruit,IApple{

    @Override
    public void print() {
        System.out.println(IFruit.name);
    }

    @Override
    public String getApple() {
        return IFruit.name;
    }
}

public class Test02 {
    public static void main(String[] args) {
        IFruit f = new bigAppleImpl();//向上转型,为父接口实例化对象
        f.print();
        IApple a = (IApple) f;
        System.out.println(a.getApple());
    }
}

输出:

在上面的程序中,IFruit,IApple两个接口可以通过它们共同的子类相互转换;(嘘...可能这个栗子不是很形象,但是基本内容已经显示出来啦)

2.接口的使用原则

(1)接口中只允许public权限;(不管是属性还是方法,其权限都是public)
在接口中,public、static、final、abstract均可以省掉不写,抽象类中一个也别想跑;
规范:接口中的属性与方法不要加任何修饰符,public也不写,保持代码的简洁性;(关于这个规范,最终解释权是:好像忘记在哪看的了,应该是阿里的编码规约)
(2)当一个子类即需要实现接口又需要继承抽象类时,先使用extends继承一个抽象类,而后使用implements实现多个接口;

栗子应该是这样的:

/**
 * @Author:Star
 * @Date:Created in 17:47 2019/10/14
 * @Description:
 */
//接口
interface IMessage{
    public void print();
}
//抽象类
abstract class News{
    public abstract void getNews();
}

class MessageImpl extends News implements IMessage{

    @Override
    public void print() {
        System.out.println("message~~~");
    }

    @Override
    public void getNews() {
        System.out.println("news~~~");
    }
}
public class Test03 {
    public static void main(String[] args) {
        IMessage message = new MessageImpl();
        message.print();
        News news = (News) message;
        news.getNews();
    }
}

输出:

(3)一个接口可以使用extends继承多个接口;

再给一个栗子哦:

interface A{
    void printA();
}

interface B{
    void printB();
}

interface C extends A,B{
    void printC();
}

class Impl implements C{
    public void printA(){}
    public void printB(){}
    public void printC(){}
}

(4)抽象类可以使用implements实现多个接口,相反,接口无法继承抽象类;(接口是更纯粹的抽象类)
(5)接口可以定义一系列的内部结构,包括:内部普通类,内部接口;其中,使用static定义的内部接口就相当于一个外部接口;

看,这颗栗子:

interface A{
    void printA();
    static interface B{
        void printB();//使用static定义,描述一个外部接口
    }
}

3.接口的应用

(1)定义标准(USB)

(2)表示能力(行为)(购买商品)

(3)在分布式开发中暴露远程服务方法

三.抽象类与接口的区别

其实,抽象类与普通类相比最大的特点是约定了子类的实现要求,但是抽象类存在单继承局限。如果要约定子类的实现要求并避免单继承局限就需要使用接口。

 

哈哈哈,有好多栗子啊,好饿,糖炒栗子和这个更配哦。

一起加油,一起进步(耶耶耶)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值