java抽象类和接口知识总结

一.抽象类

1.啥是抽象类

用专业语言描述就是:如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类

当然这话说的也很抽象,所以我们来用人话来解释一下抽象类

抛开编程语言这些,就以现实举例,我说猫的话,你头脑能马上浮现一只猫的具象,我说狗的话,你头脑能马上浮现一条狗的具象,但是当我说动物的时候,你头脑是不能浮现动物的具象,或许头脑里一会闪过鸡鸭鱼这些动物的样子,过一会又会闪过牛马羊这些动物的样子,也就是说,你找不到一个具象能够说动物具象化的样子就是这个具象,所以我们称动物就是一个抽象类。当然我们也可以继续往下再抽象,比如狗,又分为各种各样的狗,哈士奇,柴犬,斗牛犬等等,这时狗又可以被称为抽象类,如此类推,可以继续细分抽象类。所以在实际开发中,我们将什么看作为抽象类,注意还是要以实际情况为准

2.抽象类的构成结构

3.抽象类知识点

1.抽象类不能直接实例化对象,也就是说不能通过new 类名()来创建对象

2.被abstract修饰的类就是抽象类,因为是类,所以抽象类跟普通类的基本结构没什么区别,唯一的区别就是多了抽象方法区

3.抽象类的访问修饰符不能用private,抽象方法也是一样不能用private

4.抽象方法也就是被abstract修饰的方法,所以abstract不仅可以修饰类,还可以修饰方法

5.抽象方法是不能被实现的,也就是说只能在这里写个:修饰符  返回类型   方法名(参数);

6.抽象方法不能被final和static修饰

7.抽象类中不一定要有抽象方法,但有抽象方法的一定是抽象类

8.抽象类必须被继承,如果子类不重写抽象类中的抽象方法,否则子类也是抽象类,必须用abstract修饰

现在我们来理解一下这些知识

1.为什么不能实例化对象?原因就如我们刚刚解释什么是抽象类里一样,我说动物,你不能够找出一个具象说它就是动物的具象化,因为动物是有能跑能飞的,你如果说狗,但是狗不会飞,所以狗不能把动物这个抽象类全部描绘清楚,相当于数学里的包含关系,如图

2.抽象类生来就是为了被继承而诞生的,抽象类的作用就是将许多对象的共性集合起来,然后将这些共性变成抽象方法,比如吃饭,但是不同动物吃的不一样,狗吃狗粮,猫吃猫粮,牛吃草,虎吃肉,但它们这些行为整体归纳起来还是就两个字:吃饭。所以我们将这些共性放在抽象类里,继承给某个具体对象时,它能根据自身情况实现里面的方法,这也是多态的概念——即不同对象去完成时会产生不同的状态

3.所以抽象类天生就是当父亲的料,也就是说它是父类圣体,几乎可以看到抽象类就知道它是父类了,所以要想使用父类里的东西,那么它的访问权限符肯定不能是private,那不然子类怎么去实现父类的抽象方法,就相当于一个人把遗产设置为private私人的,活的时候这遗产谁都不给用,那么他就算是死了,这遗产也要连着他一起都烧了,那还怎么让子孙去继承这个遗产,所以不能用private修饰抽象类(用重写规则里的“子类重写方法的访问权限不能比父类中被重写方法的访问权限更低”也说得通,因为private是最低的访问权限了,没有比private更低的访问权限了)

4.因为抽象方法在抽象类里是不能被实现的,所以它注定是要子类被重写的,既然要被重写了,就不能再加final(final修饰变量或字段,表示变为了常量;修饰类,表示此类不能被继承;修饰方法,表示该方法不能被重写),static也是修饰方法表示此方法不能被重写,就好比嘴上说一套,私底下又一套,嘴上说大家快来重写我的抽象方法,结果私底下又给自己的抽象方法加上final或static不让这个抽象方法被重写

5.子类继承了抽象类后,子类可以重写父类中的方法,也可以不重写父类中的方法,如果不重写,那么子类也就变成了抽象类,于是又开始新的一轮继承,就相当于从祖先传下来了一个未解的秘密,如果这一代人没把这个秘密解出来,那么就传给下一代人解,直到这个秘密被解出来为止,所以会出现不同情况,一种是一开始有许多抽象方法,但每一代都实现几个抽象方法,如此类推,另一种是一开始有许多抽象方法,但每一代不仅不实现抽象方法,还在自己这一代再添加一些抽象方法,总的概括来说,就是父债子偿,出来混总该要还的

6.既然核心就是要重写父类里的方法,那么为什么一定要用抽象类呢,普通类也能被重写呀,确实如此,用普通类也能实现上述一切要求,但是使用抽象类相当于多了一重编译器的校验,如果有一天脑袋突然糊涂了,把该重写的方法没有进行重写,那么运行出来结果就会出错,这时候又要在所有的代码里面找错误,如果我们使用抽象类,就可以在我们这种犯糊涂的时候进行报错,让我们尽早发现问题。很多语法存在的意义就是为了“预防出错”,像之前的final也是类似,如果我们给不想被修改的变量加上final,那么当我们不小心修改这个变量时,编译器就会报错,及时提醒我们。

所以充分利用编译器的校验,在实际开发中是非常有意义的

4.抽象类的例子
abstract class Animal{
    //抽象方法区
    abstract public void eat();
    abstract void speak();
    //其他区
    public String name;
}
class Dog extends Animal{
    public Dog(String name){
        this.name=name;
    }
    @Override  //利用注解也能利用编译器的检查优势,提高开发效率
    public void eat(){
        System.out.println(name+"吃狗粮");
    }
    @Override
    public void speak(){
        System.out.println(name+"汪汪汪");
    }
}
class Cat extends Animal{
    public Cat(String name){
        this.name=name;
    }
    @Override
    public void eat(){
        System.out.println(name+"吃猫粮");
    }
    @Override
    public void speak(){
        System.out.println(name+"喵喵喵");
    }
}
public class Test {
    public static void main(String[] args) {
        Dog dog=new Dog("旺财");
        Cat cat=new Cat("小猫");
        dog.eat();
        dog.speak();
        cat.eat();
        cat.speak();
    }
}

二.接口

1.啥是接口

用专业语言解释:多个类的公共规范,是一种引用数据类型

用人话来说,其实和抽象类非常相似,也是将许多对象的共性放在接口里,然后每个对象重写接口里的抽象方法,实现多态。那么它存在的意义是什么呢?就要说回抽象类了,因为抽象类是用extends来继承,变成父类子类的关系,但是在Java里面,只能实现单继承,不支持多继承,所以为了解决这个问题,接口就诞生了。所以就是为了一个类可以实现多个接口。

2.接口的构成结构

3.接口知识点

1.同抽象类一样,接口也是不能被new()创建对象的,即使接口类型是一种引用类型

2.被interface修饰的就是接口,因为接口属于引用类型,不属于类,所以前面没有class了

3.如上图所示,接口中的方法都是抽象方法,即系统默认都是public abstract修饰的,也就是说,接口中的方法是不能在接口里面实现的,同时因为public abstract是系统默认修饰的,所以提高代码简洁性,一般都是不写的(例如阿里的编码规范中就要求不写public abstract)

4.如果一定要实现接口中的方法,用default或static修饰,那么可以有具体的实现(这也是与抽象类不同的地方,抽象类即使加了default和static也不能被实现)

5.同抽象类一样,接口不能被private修饰,里面的抽象方法也不能被private修饰

6.重写接口中的方法不能使用默认的访问权限,因为重写规则里的“子类重写方法的访问权限不能比父类中被重写方法的访问权限更低”可得,接口中的方法默认是public,所以也只能用public来重写接口中的方法

7.如上图所示,接口中的变量系统默认用public static final修饰,所以即使不写,也是被隐式指定的

8.接口中不能有静态代码块和构造方法

9.接口虽然不是类,但是接口编译完成后字节码文件的后缀格式也是.class

10.与继承extends不同,类连接接口用implements

11.同抽象类一样,如果一个类连接接口后,如果不想实现接口里的抽象方法,那么这个类就要定义为抽象类,然后继承给其他类,如此循环继承,直到抽象方法全部被实现才可以不变为抽象类

12.接口名一般以大写i为首字母命名

13.如果一个类既需要继承又需要连接接口,那么必须先extends再implements

4.接口的例子
class Animal{
    protected String name;

    public Animal(String name){
        this.name=name;
    }
}
interface IFlying{
    void fly();  //省略public abstract,提高代码简洁性
}
interface IRunning{
    void run();
}
interface ISwimming{
    void swim();
}
class Cat extends Animal implements IRunning{  //先extends再implements
    public Cat(String name){
        super(name);  //子类实例化前必须先初始化父类
    }
    @Override  //添加注解,利用编译器的检查优势,提高开发效率
    public void run(){  //必须用public才能重写
        System.out.println(this.name+"正在用四条腿跑");
    }
}
class Duck extends Animal implements IRunning,IFlying,ISwimming{  //实现多接口
    public Duck(String name){
        super(name);   //子类实例化前必须先初始化父类
    }
    @Override
    public void run(){
        System.out.println(this.name+"正在用两条腿跑");
    }
    @Override
    public void fly(){
        System.out.println(this.name+"正在用翅膀飞");
    }
    @Override
    public void swim(){
        System.out.println(this.name+"正在漂在水上");
    }
}
public class Test {
    public static void main(String[] args) {
        Cat cat=new Cat("neko");
        Duck duck=new Duck("唐老鸭");
        cat.run();
        duck.run();
        duck.fly();
        duck.swim();
    }
}

三.抽象类和接口的区别

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值