我們可以實例化一個抽象類嗎?

本文翻譯自:Can we instantiate an abstract class?

During one of my interview, I was asked "If we can instantiate an abstract class?" 在我的一次採訪中,有人問我“我們是否可以實例化一個抽象類?”

My reply was "No. we can't". 我的回答是“不,我們不能。” But, interviewer told me "Wrong, we can." 但是,面試官告訴我“錯了,我們可以。”

I argued a bit on this. 我對此有些爭論。 Then he told me to try this myself at home. 然後他告訴我自己在家嘗試一下。

abstract class my {
    public void mymethod() {
        System.out.print("Abstract");
    }
}

class poly {
    public static void main(String a[]) {
        my m = new my() {};
        m.mymethod();
    }
}

Here, I'm creating instance of my class and calling method of abstract class. 在這裏,我正在創建類的實例和抽象類的調用方法。 Can anyone please explain this to me? 有人可以向我解釋一下嗎? Was I really wrong during my interview? 面試中我真的錯了嗎?


#1樓

參考:https://stackoom.com/question/vMRr/我們可以實例化一個抽象類嗎


#2樓

Here, i'm creating instance of my class 在這裏,我正在創建我的課程的實例

No, you are not creating the instance of your abstract class here. 不,您不是在這裏創建抽象類的實例。 Rather you are creating an instance of an anonymous subclass of your abstract class. 而是要創建抽象類的匿名子類的實例。 And then you are invoking the method on your abstract class reference pointing to subclass object . 然後,您在抽象類引用上調用指向子類對象的方法

This behaviour is clearly listed in JLS - Section # 15.9.1 : - JLS-第15.9.1節中明確列出了此行爲:-

If the class instance creation expression ends in a class body, then the class being instantiated is an anonymous class. 如果類實例創建表達式以類主體結尾,則實例化的類是匿名類。 Then: 然後:

  • If T denotes a class, then an anonymous direct subclass of the class named by T is declared. 如果T表示一個類,則聲明由T命名的類的匿名直接子類。 It is a compile-time error if the class denoted by T is a final class. 如果T表示的類是最終類,則是編譯時錯誤。
  • If T denotes an interface, then an anonymous direct subclass of Object that implements the interface named by T is declared. 如果T表示接口,則聲明實現T命名的接口的Object的匿名直接子類。
  • In either case, the body of the subclass is the ClassBody given in the class instance creation expression. 無論哪種情況,子類的主體都是類實例創建表達式中給出的ClassBody。
  • The class being instantiated is the anonymous subclass. 被實例化的類是匿名子類。

Emphasis mine. 強調我的。

Also, in JLS - Section # 12.5 , you can read about the Object Creation Process . 另外,在JLS-第12.5節中 ,您可以閱讀有關對象創建過程的信息 I'll quote one statement from that here: - 我將在此引用一個聲明:-

Whenever a new class instance is created, memory space is allocated for it with room for all the instance variables declared in the class type and all the instance variables declared in each superclass of the class type, including all the instance variables that may be hidden. 每當創建新的類實例時,都會爲其分配存儲空間,併爲該類類型中聲明的所有實例變量和該類類型的每個超類中聲明的所有實例變量(包括所有可能隱藏的實例變量)分配空間。

Just before a reference to the newly created object is returned as the result, the indicated constructor is processed to initialize the new object using the following procedure: 在返回對新創建對象的引用作爲結果之前,使用以下過程處理指示的構造函數以初始化新對象:

You can read about the complete procedure on the link I provided. 您可以在我提供的鏈接上閱讀有關完整過程的信息。


To practically see that the class being instantiated is an Anonymous SubClass , you just need to compile both your classes. 要實際上看到要實例化的類是Anonymous SubClass ,您只需要編譯兩個類。 Suppose you put those classes in two different files: 假設您將這些類放在兩個不同的文件中:

My.java: My.java:

abstract class My {
    public void myMethod() {
        System.out.print("Abstract");
    }
}

Poly.java: Poly.java:

class Poly extends My {
    public static void main(String a[]) {
        My m = new My() {};
        m.myMethod();
    }
}

Now, compile both your source files: 現在,編譯兩個源文件:

javac My.java Poly.java

Now in the directory where you compiled the source code, you will see the following class files: 現在,在編譯源代碼的目錄中,您將看到以下類文件:

My.class
Poly$1.class  // Class file corresponding to anonymous subclass
Poly.class

See that class - Poly$1.class . 參見該類Poly$1.class It's the class file created by the compiler corresponding to the anonymous subclass you instantiated using the below code: 它是由編譯器創建的類文件,與您使用以下代碼實例化的匿名子類相對應:

new My() {};

So, it's clear that there is a different class being instantiated. 因此,很明顯,實例化了另一個類。 It's just that, that class is given a name only after compilation by the compiler. 只是,該類僅在編譯器編譯後才被命名。

In general, all the anonymous subclasses in your class will be named in this fashion: 通常,將使用以下方式來命名您的類中的所有匿名子類:

Poly$1.class, Poly$2.class, Poly$3.class, ... so on

Those numbers denote the order in which those anonymous classes appear in the enclosing class. 這些數字表示這些匿名類在封閉的類中出現的順序。


#3樓

The above instantiates an anonymous inner class which is a subclass of the my abstract class. 上面實例化了一個匿名內部類,該內部類是my抽象類的子類。 It's not strictly equivalent to instantiating the abstract class itself. 它並不完全等同於實例化抽象類本身。 OTOH, every subclass instance is an instance of all its super classes and interfaces, so most abstract classes are indeed instantiated by instantiating one of their concrete subclasses. OTOH,每個子類實例都是其所有超類和接口的實例,因此,大多數抽象類的確是通過實例化其具體的子類之一來實例化的。

If the interviewer just said "wrong!" 如果面試官只是說“錯!” without explaining, and gave this example, as a unique counterexample, I think he doesn't know what he's talking about, though. 作爲一個獨特的反例,我認爲他不知道他在說什麼。


#4樓

= my() {}; means that there's an anonymous implementation, not simple instantiation of an object, which should have been : = my() . 意味着有一個匿名實現,而不是對象的簡單實例化,應該是: = my() You can never instantiate an abstract class. 您永遠不能實例化一個抽象類。


#5樓

Abstract classes cannot be instantiated, but they can be subclassed. 抽象類不能實例化,但是可以被子類化。 See This Link 查看此鏈接

The best example is 最好的例子是

Although Calender class has a abstract method getInstance() , but when you say Calendar calc=Calendar.getInstance(); 儘管Calender類具有抽象方法getInstance() ,但是當您說Calendar calc=Calendar.getInstance();

calc is referring to the class instance of class GregorianCalendar as "GregorianCalendar extends Calendar " calc將類GregorianCalendar的類實例稱爲“ GregorianCalendar擴展Calendar

Infact annonymous inner type allows you to create a no-name subclass of the abstract class and an instance of this. 實際上的匿名內部類型 允許您創建抽象類的 無名 子類及其實例。


#6樓

Just observations you could make: 您可以進行以下觀察:

  1. Why poly extends my ? 爲什麼poly伸出my This is useless... 這沒用...
  2. What is the result of the compilation? 編譯的結果是什麼? Three files: my.class , poly.class and poly$1.class 三個文件: my.classpoly.classpoly$1.class
  3. If we can instantiate an abstract class like that, we can instantiate an interface too... weird... 如果我們可以像這樣實例化一個抽象類,我們也可以實例化一個接口。


Can we instantiate an abstract class? 我們可以實例化一個抽象類嗎?

No, we can't. 不,我們不能。 What we can do is, create an anonymous class (that's the third file) and instantiate it. 我們可以做的是,創建一個匿名類(這是第三個文件)並實例化它。


What about a super class instantiation? 那麼超類實例化呢?

The abstract super class is not instantiated by us but by java. 抽象的超類不是由我們實例化的,而是由java實例化的。

EDIT: Ask him to test this 編輯:請他測試一下

public static final void main(final String[] args) {
    final my m1 = new my() {
    };
    final my m2 = new my() {
    };
    System.out.println(m1 == m2);

    System.out.println(m1.getClass().toString());
    System.out.println(m2.getClass().toString());

}

output is: 輸出爲:

false
class my$1
class my$2
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章