详解Java抽象类与普通类的区别

 更新时间:2021年06月13日 09:10:52   作者:Lf_MrF  
今天给大家带来的是关于Java的相关知识,文章围绕着Java抽象类与普通类的区别展开,文中有非常详细的介绍及代码示例,需要的朋友可以参考下

浅谈抽象类

在面向对象概念中,所有的对象都是通过类来描述的,但是反过来,并不是所有的类都是用来描述对象的.如果一个类中没有足够多的信息来描述一个具体的对象,这样的类就是抽象类。

看到这里可能还是觉得有些难以理解,举个例子说明一下:说到动物你会想到什么?猫,狗,鸡鸭鹅?当然这些都可以.那么动物这两个字,你能确定一个具体的对象吗?显然不能.甚至更严格意义上讲,说到猫你会想到什么?橘猫,短美…

毕竟:

一千个人心中有一千个哈姆雷喵.

所以我们在设计中,动物类可以设计成为抽象类,而某一种特定的物种可以采用通过继承动物类实现.

多态这部分我理解了好久,有一天突然就会用了,也明白所谓的父类引用指向子类对象是什么意思了.但是写完前面发现,自己明白了讲出来还是很模糊.多态真的是很重要很重要的一个点,要好好体会这部分.

抽象类和普通类的区别是什么?

抽象类的语法规则

抽象类的语法规则:abstract关键字修饰

1.抽象类不可以被实例化.

2.抽象类不定有抽象方法.

3.一个类中如果有抽象方法,那么这个类一定是抽象类.

4.抽象类中可以存在普通属性、方法、静态属性和静态方法.

5.抽象类中可以存在构造方法.

public abstract class AbstractObject{
	// 普通属性
    String name;
	// 构造方法
    public AbstractObject(String name) {
        this.name = name;
    }
    // 静态方法 - 类名访问
    public static void staticMethod(){
        System.out.println("抽象类可以有静态方法.");
    }
	// 抽象方法
    public abstract void move();
	// 普通方法
    public void commonMethod(String food){
        System.out.println("抽象类可以有普通方法.");
    }
}

抽象类不可以实例化

这部分可以直接暂时记住结论,整个过程可以暂时先跳过后面补,按照我的学习经历(基础差到爆),这部分直接看会很懵.

定义一个动物的抽象类,动物总得动吧(并不!)所以定义一个共性的move()方法.

public abstract class Animal {
    String name;
    public Animal(String name) {
        this.name = name;
    }
    public abstract void move();
}

当我使用IDEA写示例的时候直接出现了第二种情况!见鬼了抽象类new出来了!

public class Test {
    public static void main(String[] args) {
    	// 抽象类不能实例化!会直接报编译期错误!
        //标红信息: 'Animal' is abstract; cannot be instantiated
        Animal animal = new Animal("小猫");
        // 第二种情况
        Animal animalObjcet = new Animal("小猫") {
            @Override
            public void move() {
                System.out.println("我开始移动了!");
            }
        };
    }
}

关于第二种情况的解释 - 扩展知识:匿名内部类(可跳过)

这里涉及到了一个知识点叫做匿名内部类.
匿名内部类的格式如下:

new 类名或者接口名(){
	重写方法;
}
// 放到一起对比看,很明显后面的是一个匿名内部类
new Animal("小猫") {
    @Override
    public void move() {
        System.out.println("我开始移动了!");
    }
};

匿名:这个类没有名字
内部类:存在于某个类的内部的类.

它实际上是继承并实现了Animal抽象类的一个子类.也就是说这里并不是实例化出了Animal类,这个简便的写法相当于我们进行了如下的写法.

public class AnimalObject extends Animal{
    public AnimalObject(String name) {
        super(name);
    }
    @Override
    public void move() {
        System.out.println("我是一只能动的动物!");
    }
}

public class Test {
    public static void main(String[] args) {
        AnimalObject animalObject = new AnimalObject("我是动物抽象类的子类");
        animalObjcet.move();	// 我是一只能动的动物!
    }
}

抽象类的子类

注意:这里有一个需要强调的地方,对于抽象类中的方法我们的用词应该是实现.对于已经实现了的方法,我们的用词才可以是重写.写到后面发现了前面描述过程中我用词都是重写这里进行了修正.
错误写法:不重写(Override)抽象类中的抽象方法
正确写法:不实现(Implement)抽象类中的抽象方法
再次补充:好像说成重写也不能算错误,IDEA自动生成的里面也加了 @Override 注解.就不继续修改了.

1.不实现抽象类中的抽象方法

当不对抽象类中的抽象方法进行重写的时候,子类一定也是抽象类.(有抽象方法的类一定是抽象类)

public abstract class AbstractCat extends Animal{
    Integer weight;
    public AbstractCat(String name, Integer weight) {
        super(name);    // 继承父类的名称
        this.weight = weight; // 猫咪的年龄
    }
    // 这个是没有重写,依旧是了抽象方法
    public abstract void move();
    // 注意:下面这种写法是重写过之后的!只是方法体为空.
    // public void move(){};
}

2.实现抽象类中的抽象方法

当对抽象类中的所有抽象方法进行实现之后,现在的猫咪类可以是一个普通类了.

public class Cat extends AbstractCat{
    public Cat(String name, Integer weight) {
        super(name, weight);
    }
    @Override
    public void move() {
        System.out.println("一只奔跑的重达" + weight + "kg的" + name);
    }
}

测试一下:

public class Test {
    public static void main(String[] args) {
        Cat cat = new Cat("橘猫", 20);
        cat.move();	// 一只奔跑的重达20kg的橘猫
    }
}

好了到这里,属于你的橘猫终于跑起来了!

关于实现抽象方法的延伸

我看很多文章都说要子类要重写(重写是错误的!这里更正为实现)父类的抽象方法,抽象方法.那我如果只实现部分抽象方法呢?
第一步:改造Animal类

public abstract class Animal {
    String name;
    public Animal(String name) {
        System.out.println("我是动物的构造方法!");
        this.name = name;
    }
    // 多添加几个抽象方法
    public abstract void move();
    public abstract void eat();
    public abstract void sleep();
}

第二步:AbstractCat 类中实现部分抽象方法

// 不添加 abstract 关键字会报错
// Class 'AbstractCat' must either be declared abstract or implement abstract method 'move()' in 'Animal'
public abstract class AbstractCat extends Animal{
    Integer weight;
    public AbstractCat(String name, Integer weight) {
        super(name);
        System.out.println("我是抽象猫咪的构造方法!");
        // 继承父类的名称
        this.weight = weight; // 猫咪的年龄
    }
    @Override
    public void eat() {
        System.out.println(this.name + "在吃猫粮");
    }
    @Override
    public void sleep() {
        System.out.println(this.name + "睡觉了!");
    }
}

第三步:Cat类登场

public class Cat extends AbstractCat{

    public Cat(String name, Integer weight) {
        super(name, weight);
    }
    /*
    sleep方法和eat方法已经在父类中实现过了,所以这里只剩下最后一个 move 是需要实现的抽象方法.
	*/
    @Override
    public void move() {
        System.out.println("重达" + weight + "kg的" + this.name + "在懒洋洋的跑");
    }
}

小结

1.普通类可以实例化调用,但是抽象类不可以,因为抽象类只是一种概念,无法映射为具体的对象.

2.普通类和抽象类都可以被继承,但是抽象类被继承之后,子类需要重写抽象类中的全部抽象方法,否则子类必须是一个抽象类.

参考和扩展阅读

Java基础系列第一弹之方法重载和方法重写的区别
Java基础系列第二弹之Java多态成员访问的特点
Java基础系列第三弹之操作字符串的类都有哪些?区别是什么?

到此这篇关于详解Java抽象类与普通类的区别的文章就介绍到这了,更多相关Java抽象类与普通类内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • windows上nacos自启动的三种方法小结

    windows上nacos自启动的三种方法小结

    本文主要给大家介绍了windows上nacos自启动的三种方法,借助WinSW.exe添加到服务列表,修改nacos启动配置以及以开机"启动"方式——启动Nacos的startup.cmd这三种方法,文中通过图文讲解的非常详细,需要的朋友可以参考下
    2023-12-12
  • MyBatis动态SQL标签用法实例详解

    MyBatis动态SQL标签用法实例详解

    本文通过实例代码给大家介绍了MyBatis动态SQL标签用法,非常不错,具有参考借鉴价值,需要的朋友参考下吧
    2017-07-07
  • Java开发岗位面试被问到反射怎么办

    Java开发岗位面试被问到反射怎么办

    这篇文章主要介绍了java 面向对象面试集锦的相关资料,这里整理了面向对象的基础知识,帮助大家学习理解此部分的知识,需要的朋友可以参考下
    2021-07-07
  • Java并发编程学习之ThreadLocal源码详析

    Java并发编程学习之ThreadLocal源码详析

    这篇文章主要给大家介绍了关于Java并发编程学习之源码分析ThreadLocal的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-06-06
  • 简单了解SpringMVC常用组件作用解析

    简单了解SpringMVC常用组件作用解析

    这篇文章主要介绍了简单了解SpringMVC常用组件作用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • Java实现的动态数字时钟功能示例【显示世界时间】

    Java实现的动态数字时钟功能示例【显示世界时间】

    这篇文章主要介绍了Java实现的动态数字时钟功能,结合实例形式分析了java显示北京、纽约、伦敦等世界时间的相关日期时间运算操作技巧,需要的朋友可以参考下
    2019-03-03
  • 详解Java之路(五) 访问权限控制

    详解Java之路(五) 访问权限控制

    本篇文章主要介绍了Java之路(五) 访问权限控制 ,小编觉得挺不错的,现在分享给大家,也给大家做个参考。
    2016-12-12
  • 基于Java中对域和静态方法的访问不具有多态性(实例讲解)

    基于Java中对域和静态方法的访问不具有多态性(实例讲解)

    下面小编就为大家带来一篇基于Java中对域和静态方法的访问不具有多态性(实例讲解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10
  • Java核心库实现简单的AOP

    Java核心库实现简单的AOP

    这篇文章主要介绍了如何用Java核心库实现简单的AOP,帮助大家为了更好的理解和学习AOP的思想,感兴趣的朋友可以了解下
    2020-08-08
  • Java实现JDBC向数据库批量插入

    Java实现JDBC向数据库批量插入

    在Java项目中可能会出现大量向数据库中插入的情况,本文主要介绍了Java实现JDBC向数据库批量插入,具有一定的参考价值,感兴趣的可以了解一下
    2023-09-09

最新评论