抽象類能實例化嗎?
本文轉自: https://www.cnblogs.com/zyx110/p/ 10648119.html
這個問題我想了一個晚上,看了好幾篇別人的博客,但結果都各不相同,每個人有每個人的理解,后來我想明白了:
抽象類不能直接通過new去實例化一個對象,那它就是不能實例化,要獲取抽象類的對象, 需要先用一個類繼承抽象類, 然后去實例化子類。也可以用匿名內部類,在抽象類中創建一個匿名的子類,繼承抽象類,通過特殊的語法實例化子類的對象 。(后面會細說)
現在重點來了,要研究這個問題,前提是你要了解抽象類,萬變不離其宗,我們從抽象類的根源談起 , 深化對抽象類的理解。
首先看這個例子:
package com.my.animal;
//動物類
public class Animal {
String name;//名字
String color;//顏色
public Animal(String name,String color){
this.name = name;
this.color = color;
}
public void run(){
System.out.println(name+"四條腿跑的很快!!!");
}
}
//狗類繼承動物類
class Dog extends Animal{
public Dog(String name,String color){
super(name,color);
}
}
//魚類繼承動物類
class Fish extends Animal{
public Fish(String name, String color) {
super(name, color);
}
}
class Test{
public static void main(String[] args) {
Dog dog = new Dog("哈巴狗","白色");
dog.run();
Fish fish = new Fish("錦鯉","紅色");
fish.run();
}
}
|
1
2
3
4
|
運行結果:
哈巴狗四條腿跑的很快!!!
錦鯉四條腿跑的很快!!!
|
是不是發現問題了,魚怎么能用腿跑呢,難道是原始魚?哈哈,開玩笑的,這個問題如何解決,估計大家馬上想到了,在子類中重寫父類的run方法不就行了,對,確實這樣就可以解決,但是大家想過沒有,我們是如何發現這個問題的?是不是編譯運行之后才看到的,當然,也有大佬能不編譯運行就能看到,不抬杠啊,意思是說有發現不了這個問題的風險,對別人可能無所謂,但對我們程序員來說,這種低級錯誤還是不犯的好,程序員應該有更高的追求,豈能在這被絆倒,我們要把這種風險降為零,那該如何做呢?不急,心急吃不了熱豆腐,且看我慢慢分析:
目前存在的問題:
1.動物類的run方法描述的不正確
2.沒有強制要子類一定要重寫父類的run方法
解決方案:(抽象類的應用場景)
我們在描述一類事物的時候,發現該種事物確實存在着某種行為,但是這種行為目前是不具體的,那么我們可以抽取這種行為的聲明,但是不去實現該種行為,這時候這種行為我們稱作為抽象的行為,我們就需要使用抽象類
先看下面的例子:
package com.my.animal;
//動物類(抽象類)
public abstract class Animal {
String name;//名字
String color;//顏色
//構造方法
public Animal(String name,String color){
this.name = name;
this.color = color;
}
//非抽象方法
public void eat(){
System.out.println(name+"吃東西!!!");
}
//抽象方法
public abstract void run();
}
class Dog extends Animal{
public Dog(String name,String color){
super(name,color);
}
@Override
public void run() {
System.out.println(name+"四條腿跑得快!!");
}
}
class Fish extends Animal{
public Fish(String name, String color) {
super(name, color);
}
@Override
public void run() {
System.out.println(name+"搖搖尾巴游啊游!!");
}
}
class Test{
public static void main(String[] args) {
Dog dog = new Dog("哈巴狗","白色");
dog.run();
Fish fish = new Fish("錦鯉","紅色");
fish.run();
}
}
|
1
2
3
4
|
運行結果:
哈巴狗四條腿跑得快!!
錦鯉搖搖尾巴游啊游!!
|
這個問題解決了,那還有一個問題就是:抽象類能實例化對象嗎?
看這個例子就知道了:
public abstract class Animal {
String name;
String color;
public Animal(String name,String color){
this.name = name;
this.color = color;
}
public abstract void run();
}
class Test{
public static void main(String[] args) {
Animal a = new Animal();
a.run();
}
}
|
1
2
3
|
運行結果:
Error:(
45
,
20
) java: com.my.animal.Animal是抽象的; 無法實例化
|
抽象類注意的細節:
1.如果一個函數沒有方法體,那么該函數必須要使用abstract修飾,把該函數修飾成抽象的函數。
2.如果一個類出現了抽象的函數,那么該類也必須使用abstract修飾。
3.如果一個非抽象類繼承了抽象類,那么必須要把抽象類的所有抽象方法全部實現。
4.抽象類可以存在抽象方法,也可以存在非抽象方法,還可以不存在抽象方法,但是這樣沒任何意義,Java是不寫廢話的。
5.抽象類是不能實例化對象的
6.抽象類是存在構造函數的,其構造函數是提供給子類創建對象的時候初始化父類的屬性的。
疑問:為什么抽象類不能實例化對象?
因為抽象類是存在抽象方法的,如果能讓抽象類創建對象的話,那么使用抽象類的對象調用抽象方法是沒有任何意義的。
疑問排解了,故事結束了?不,學海本無底,我們來點擴展,就是開頭提到的如何用匿名內部類去實例化子類對象。
看下面的例子:
package Practice_Anything;
public class Java_Abstract2 {
public void a(){
System.out.println("我是抽象類中的一個非抽象方法");
}
public static Java_Abstract2 newIntences(){
return new Java_Abstract2(){
};
}
}
class Test2{
public static void main(String[] args) {
Java_Abstract2 java_abstract2 = Java_Abstract2.newIntences();
java_abstract2.a();
}
}
|
1
2
3
|
運行結果:
我是抽象類中的一個非抽象方法
|
