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

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

[[374905]]

本文转载自微信公众号「 见贤思编程」,作者 泰斗贤若如。转载本文请联系 见贤思编程公众号。

前言

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

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

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

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

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

抽象类不能实例化

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

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

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

首先看这个例子:

  1. package com.my.animal; 
  2.  
  3.  
  4.  
  5.  
  6. //动物类 
  7.  
  8. public class Animal { 
  9.  
  10. String name;//名字 
  11.  
  12. String color;//颜色 
  13.  
  14.  
  15.  
  16.  
  17. public Animal(String name,String color){ 
  18.  
  19. this.name = name
  20.  
  21. this.color = color; 
  22.  
  23.  
  24. public void run(){ 
  25.  
  26. System.out.println(name+"四条腿跑的很快!!!"); 
  27.  
  28.  
  29.  
  30. //狗类继承动物类 
  31.  
  32. class Dog extends Animal{ 
  33.  
  34. public Dog(String name,String color){ 
  35.  
  36. super(name,color); 
  37.  
  38.  
  39.  
  40. //鱼类继承动物类 
  41.  
  42. class Fish extends Animal{ 
  43.  
  44.  
  45.  
  46.  
  47. public Fish(String name, String color) { 
  48.  
  49. super(name, color); 
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56. class Test{ 
  57.  
  58. public static void main(String[] args) { 
  59.  
  60. Dog dog = new Dog("哈巴狗","白色"); 
  61.  
  62. dog.run(); 
  63.  
  64.  
  65.  
  66.  
  67. Fish fish = new Fish("锦鲤","红色"); 
  68.  
  69. fish.run(); 
  70.  
  71.  

运行结果:

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

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

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

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

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

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

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

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

目前存在的问题:

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

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

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

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

先看下面的例子:

  1. package com.my.animal; 
  2.  
  3. //动物类(抽象类) 
  4.  
  5. public abstract class Animal { 
  6.  
  7. String name;//名字 
  8.  
  9. String color;//颜色 
  10.  
  11. //构造方法 
  12.  
  13. public Animal(String name,String color){ 
  14.  
  15. this.name = name
  16.  
  17. this.color = color; 
  18.  
  19.  
  20. //非抽象方法 
  21.  
  22. public void eat(){ 
  23.  
  24. System.out.println(name+"吃东西!!!"); 
  25.  
  26.  
  27. //抽象方法 
  28.  
  29. public abstract void run(); 
  30.  
  31.  
  32.  
  33.  
  34.  
  35. class Dog extends Animal{ 
  36.  
  37. public Dog(String name,String color){ 
  38.  
  39. super(name,color); 
  40.  
  41.  
  42.  
  43.  
  44.  
  45. @Override 
  46.  
  47. public void run() { 
  48.  
  49. System.out.println(name+"四条腿跑得快!!"); 
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56. class Fish extends Animal{ 
  57.  
  58.  
  59.  
  60.  
  61. public Fish(String name, String color) { 
  62.  
  63. super(name, color); 
  64.  
  65.  
  66.  
  67.  
  68.  
  69. @Override 
  70.  
  71. public void run() { 
  72.  
  73. System.out.println(name+"摇摇尾巴游啊游!!"); 
  74.  
  75.  
  76.  
  77.  
  78.  
  79.  
  80. class Test{ 
  81.  
  82. public static void main(String[] args) { 
  83.  
  84. Dog dog = new Dog("哈巴狗","白色"); 
  85.  
  86. dog.run(); 
  87.  
  88.  
  89.  
  90.  
  91. Fish fish = new Fish("锦鲤","红色"); 
  92.  
  93. fish.run(); 
  94.  
  95.  

运行结果:

哈巴狗四条腿跑得快!!

锦鲤摇摇尾巴游啊游!!

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

看这个例子就知道了:

  1.  
  2. String name
  3.  
  4. String color; 
  5.  
  6.  
  7.  
  8.  
  9. public Animal(String name,String color){ 
  10.  
  11. this.name = name
  12.  
  13. this.color = color; 
  14.  
  15.  
  16. public abstract void run(); 
  17.  
  18.  
  19.  
  20.  
  21.  
  22. class Test{ 
  23.  
  24. public static void main(String[] args) { 
  25.  
  26. Animal a = new Animal(); 
  27.  
  28. a.run(); 
  29.  
  30.  

运行结果:

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

抽象类注意的细节:

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

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

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

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

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

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

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

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

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

看下面的例子:

  1. public class Java_Abstract2 { 
  2.  
  3.  
  4.  
  5.  
  6. public void a(){ 
  7.  
  8. System.out.println("我是抽象类中的一个非抽象方法"); 
  9.  
  10.  
  11.  
  12.  
  13.  
  14. public static Java_Abstract2 newIntences(){ 
  15.  
  16. return new Java_Abstract2(){ 
  17.  
  18.  
  19.  
  20.  
  21. }; 
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28. class Test2{ 
  29.  
  30. public static void main(String[] args) { 
  31.  
  32. Java_Abstract2 java_abstract2 = Java_Abstract2.newIntences(); 
  33.  
  34. java_abstract2.a(); 
  35.  
  36.  

运行结果:

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

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

 

责任编辑:武晓燕 来源: 见贤思编程
相关推荐

2009-08-03 18:12:31

C#抽象类

2009-09-04 13:31:33

C#抽象类

2011-06-28 10:55:20

C#接口抽象类

2012-02-29 09:32:01

Java

2010-03-04 09:40:04

Java接口抽象类

2009-12-02 14:55:46

PHP抽象类abstr

2009-06-29 15:15:00

抽象类Java

2009-11-02 17:49:05

VB.NET抽象类

2009-12-07 14:53:13

PHP抽象类应用

2011-07-12 15:58:48

java抽象类接口

2009-04-30 15:15:01

Java抽象类接口

2010-01-14 18:08:08

VB.NET抽象类

2009-08-10 10:04:25

C#抽象类C#接口

2011-07-10 14:07:59

JAVA

2015-03-23 09:33:43

Java抽象类Java接口Java

2011-12-22 10:48:21

Java

2009-06-16 11:30:00

Java抽象类Java接口

2009-06-14 21:31:29

Java抽象类Java接口

2011-07-06 10:33:31

C#

2011-05-19 18:01:56

JAVA
点赞
收藏

51CTO技术栈公众号