抽象类能实例化吗?口气很强硬的说:“不能”!

程序员私房菜

共 4062字,需浏览 9分钟

 · 2021-04-01

抽象类能实例化吗?口气很强硬的说:“不能”!

前言

针对这个问题,在 19 年我在博客园专门写过一篇博客,为什么突然翻出来呢?

昨晚有个大二的学弟专门加我好友来问我这个问题,当时他问我的时候,我居然不知道该怎么回答他了,我知道不能,但一时说不出原因,可见 Java 基础确实需要补补课了。

忘了也是正常的,就怕你知道你忘了,还无动于衷,这就说不过去了。

于是乎,我进博客园把两年前的博客给扒出来了,先自己温习了一遍,然后给学弟讲了一遍,现在我觉得我又行了(打脸)。

不翻不知道,一翻变了样。就这问题,居然有 13000+ 的阅读量,说明关注这问题或者被这个问题所迷惑的人还不少,于是乎,小牛 把这篇博客又搬运到公众号上了,也许还有读者不知道。


抽象类不能实例化

抽象类不能直接通过 new 去实例化一个对象,那它就是不能实例化,要获取抽象类的对象,需要先用一个类继承抽象类,然后去实例化子类。


也可以用匿名内部类,在抽象类中创建一个匿名的子类,继承抽象类,通过特殊的语法实例化子类的对象(这个后面会详细解释) 。


现在重点来了,要研究这个问题,前提是你要了解抽象类,万变不离其宗,我们从抽象类的根源谈起 ,深化对抽象类的理解。


首先看这个例子:

  1. package com.my.animal;


  2. //动物类

  3. public class Animal {

  4. String name;//名字

  5. String color;//颜色


  6. public Animal(String name,String color){

  7. this.name = name;

  8. this.color = color;

  9. }

  10. public void run(){

  11. System.out.println(name+"四条腿跑的很快!!!");

  12. }

  13. }

  14. //狗类继承动物类

  15. class Dog extends Animal{

  16. public Dog(String name,String color){

  17. super(name,color);

  18. }

  19. }

  20. //鱼类继承动物类

  21. class Fish extends Animal{


  22. public Fish(String name, String color) {

  23. super(name, color);

  24. }

  25. }


  26. class Test{

  27. public static void main(String[] args) {

  28. Dog dog = new Dog("哈巴狗","白色");

  29. dog.run();


  30. Fish fish = new Fish("锦鲤","红色");

  31. fish.run();

  32. }

  33. }

运行结果:  

哈巴狗四条腿跑的很快!!!

锦鲤四条腿跑的很快!!!

是不是发现问题了,鱼怎么能用腿跑呢,难道是原始鱼?


哈哈,开玩笑的,这个问题如何解决?估计大家马上想到了,在子类中重写父类的 run 方法不就行了。


对,确实这样就可以解决,但是大家想过没有,我们是如何发现这个问题的?


是不是编译运行之后才看到的,当然,也有大佬能不编译运行就能看到,不抬杠啊。


意思是说有发现不了这个问题的风险,对别人可能无所谓,但对我们程序员来说,这种低级错误还是不犯的好,程序员应该有更高的追求,岂能在这被绊倒,我们要把这种风险降为零,那该如何做呢?


不急,心急吃不了热豆腐,且看我慢慢分析:


目前存在的问题:

1.动物类的run方法描述的不正确

2.没有强制要子类一定要重写父类的run方法


解决方案:(抽象类的应用场景)


我们在描述一类事物的时候,发现该种事物确实存在着某种行为,但是这种行为目前是不具体的,那么我们可以抽取这种行为的声明,但是不去实现该种行为,这时候这种行为我们称作为抽象的行为,我们就需要使用抽象类


先看下面的例子: 

  1. package com.my.animal;

  2. //动物类(抽象类)

  3. public abstract class Animal {

  4. String name;//名字

  5. String color;//颜色

  6. //构造方法

  7. public Animal(String name,String color){

  8. this.name = name;

  9. this.color = color;

  10. }

  11. //非抽象方法

  12. public void eat(){

  13. System.out.println(name+"吃东西!!!");

  14. }

  15. //抽象方法

  16. public abstract void run();

  17. }


  18. class Dog extends Animal{

  19. public Dog(String name,String color){

  20. super(name,color);

  21. }


  22. @Override

  23. public void run() {

  24. System.out.println(name+"四条腿跑得快!!");

  25. }

  26. }


  27. class Fish extends Animal{


  28. public Fish(String name, String color) {

  29. super(name, color);

  30. }


  31. @Override

  32. public void run() {

  33. System.out.println(name+"摇摇尾巴游啊游!!");

  34. }

  35. }


  36. class Test{

  37. public static void main(String[] args) {

  38. Dog dog = new Dog("哈巴狗","白色");

  39. dog.run();


  40. Fish fish = new Fish("锦鲤","红色");

  41. fish.run();

  42. }

  43. }

运行结果:  

哈巴狗四条腿跑得快!!

锦鲤摇摇尾巴游啊游!!

这个问题解决了,那下面解决的问题就是:抽象类能实例化对象吗?


看这个例子就知道了:

  1. public abstract class Animal {

  2. String name;

  3. String color;


  4. public Animal(String name,String color){

  5. this.name = name;

  6. this.color = color;

  7. }

  8. public abstract void run();

  9. }


  10. class Test{

  11. public static void main(String[] args) {

  12. Animal a = new Animal();

  13. a.run();

  14. }

  15. }

运行结果:  

Error:(45,20) java:com.my.animal.Animal是抽象的;无法实例化

抽象类注意的细节:

1.如果一个函数没有方法体,那么该函数必须要使用abstract修饰,把该函数修饰成抽象的函数。

2.如果一个类出现了抽象的函数,那么该类也必须使用abstract修饰。

3.如果一个非抽象类继承了抽象类,那么必须要把抽象类的所有抽象方法全部实现。

4.抽象类可以存在抽象方法,也可以存在非抽象方法,还可以不存在抽象方法,但是这样没任何意义,Java是不写废话的。

5.抽象类是不能实例化对象的

6.抽象类是存在构造函数的,其构造函数是提供给子类创建对象的时候初始化父类的属性的。      

 疑问:为什么抽象类不能实例化对象?


 因为抽象类是存在抽象方法的,如果能让抽象类创建对象的话,那么使用抽象类的对象调用抽象方法是没有任何意义的。


疑问排解了,故事结束了?不,学海本无底,我们来点扩展,就是开头提到的如何用匿名内部类去实例化子类对象。


看下面的例子:

  1. public class Java_Abstract2 {


  2. public void a(){

  3. System.out.println("我是抽象类中的一个非抽象方法");

  4. }


  5. public static Java_Abstract2 newIntences(){

  6. return new Java_Abstract2(){


  7. };

  8. }

  9. }


  10. class Test2{

  11. public static void main(String[] args) {

  12. Java_Abstract2 java_abstract2 = Java_Abstract2.newIntences();

  13. java_abstract2.a();

  14. }

  15. }

运行结果:  

我是抽象类中的一个非抽象方法

这个问题到这就结束了,但是学习还没有停止,比如接口也是一种抽象类型,是抽象方法的集合,由此,我们是不是该联想到学习接口了呢?忘了的同学该复习了哈!


学海本无底,前行莫彷徨!


我已经更新了《10万字Springboot经典学习笔记》,点击下面小卡片,进Java开发宝典】,回复:笔记,即可免费获取。

点赞是最大的支持 

浏览 11
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报