本文转载自微信公众号《看见人才,思考编程》,院长贤若如所著。转载本文请联系简鲜丝编程公众号。前言针对这个问题,我2019年在博客园写了一篇博客,怎么突然就出来了?昨天晚上,一个大二的同学加我为好友来问我这个问题。当他问我的时候,我不知道怎么回答他,我知道我不能,但是我一时说不出原因,可见Java的基础知识确实需要补课。忘记也是正常的。怕你知道自己忘记了,还无动于衷,这不合情理。于是,我走进了博客园,拿起了两年前的博客。我自己复习过,然后告诉我的后辈。现在我觉得我可以再来一次(打脸)。不翻不知道,一翻就变了。在这个问题上,居然有13000+的阅读量,说明关注这个问题或者被这个问题搞糊涂的人还是很多的,所以小牛又把这个博客移到了公众号,可能还有读者有不知道。抽象类不能被实例化抽象类不能直接通过new实例化一个对象,那么就不能被实例化。要获得一个抽象类的对象,需要先用类继承抽象类,然后再实例化子类。也可以使用匿名内部类在抽象类中创建匿名子类,继承抽象类,通过特殊的语法实例化子类的对象(后面会详细解释)。现在重要的一点来了。研究这个问题,前提是你需要了解抽象类,抽象类永远都是一样的。下面说说抽象类的根源,加深对抽象类的理解。先看这个例子:packagecom.my.animal;//动物类publicclassAnimal{Stringname;//nameStringcolor;//colorpublicAnimal(Stringname,Stringcolor){this.name=name;this.color=color;}publicvoidrun(){System.out.println(name+"四条腿跑得快!!!");}}//狗类继承动物类DogextendsAnimal{publicDog(Stringname,Stringcolor){super(name,color);}}//Fish继承了动物classFishextendsAnimal{publicFish(Stringname,Stringcolor){super(name,color);}}classTest{publicstaticvoidmain(String[]args){Dogdog=newDog("Pug","White");dog.run();Fishfish=newFish("Koi","Red");fish.run();}}运行结果:哈巴狗四条腿跑得很快!!!锦鲤四条腿跑得快!!!是不是发现问题了,鱼怎么会用腿跑,难道是原始鱼吗?哈哈,开玩笑的,这个问题怎么解决呢?估计大家第一时间就想到了,直接在子类中重写父类的run方法即可。是的,确实可以解决这个问题,但是你有没有想过我们是怎么发现这个问题的?是编译运行后才看到的吗?当然有些大佬不用编译运行也能看到。这意味着存在无法发现此问题的风险。在别人看来可能无所谓,但对于我们程序员来说,这种低级错误还是不要犯为好。程序员应该有更高的追求。我们怎么会在这里绊倒呢?我们想把这个风险降到零,那么应该怎么做呢?别着急,热豆腐吃不着急,我慢慢分析:目前存在的问题:1.动物类run方法描述不正确2.子类不强制重写父类的运行方法。解决方法:(抽象类的应用场景)当我们描述一个类的事物时,发现确实存在这种事物的某种行为,但是这种行为目前是不具体的,那么我们可以抽取其声明这种行为,但不实现这种行为。这时,这种行为就称为抽象行为。我们需要使用抽象类先看下面的例子:packagecom.my。animal;//动物类(抽象类)publicabstractclassAnimal{Stringname;//nameStringcolor;//color//构造方法publicAnimal(Stringname,Stringcolor){this.name=name;this.color=color;}//非abstractMethodpublicvoideat(){System.out.println(name+"Eat!!!");}//抽象方法publicabstractvoidrun();}classDogextendsAnimal{publicDog(Stringname,Stringcolor){super(name,color);}@Overridepublicvoidrun(){System.out.println(name+"四条腿跑得快!!");}}classFishextendsAnimal{publicFish(Stringname,Stringcolor){super(name,color);}@Overridepublicvoidrun(){System.out.println(name+"摇尾巴!!");}}classTest{publicstaticvoidmain(String[]args){Dogdog=newDog("Pug","White");dog.run();Fishfish=newFish("t;koi","re??d");fish.run();}}运行结果:哈巴狗四条腿跑得很快!!锦鲤摇着尾巴游来游去!!这个问题解决了,那么下面的问题就解决了是:抽象类可以实例化对象吗?看看这个例子:]args){Animala=newAnimal();a.run();}}运行结果:Error:(45,20)java:com.my.animal.Animalisabstract;abstractclasscannotbeinstantiatedNote详情:1.如果一个函数没有方法体,那么这个函数必须用abstract修饰,使这个函数成为抽象函数。2.如果一个类有一个抽象函数,那么这个类也必须用abstract修饰。3.如果一个非抽象类继承一个抽象类,则必须实现抽象类的所有抽象方法。4.抽象类可以有抽象方法,也可以有非抽象方法,也可以没有abstractmethods,但这不任何意义上,Java不写废话。5、抽象类不能实例化对象。6、抽象类有构造函数,其构造函数提供给子类,用于在创建对象时初始化父类的属性。问题:为什么抽象类不能实例化对象?因为抽象类有抽象方法。如果抽象类可以创建对象,那么用抽象类对象调用抽象方法就没有任何意义。问题解决了,故事就结束了?不行,学海无底,我们来展开,也就是开头说的匿名内部类如何实例化子类对象。请看下面的例子:publicclassJava_Abstract2{publicvoida(){System.out.println("我是一个抽象类中的非抽象方法");}publicstaticJava_Abstract2newIntences(){returnnewJava_Abstract2(){};}}classTest2{publicstaticvoidmain(String[]args){Java_Abstract2java_abstract2=Java_Abstract2.newIntences();java_abstract2.a();}}运行结果:我是一个抽象类中的非抽象方法这个问题结束了,但是学习还没有停止,比如interfacesAn抽象类型是抽象方法的集合。由此,我们是不是应该想到学习界面呢?忘记的同学要复习一下!
