面试:我们可以实例化抽象类吗? [英] Interview: Can we instantiate abstract class?

查看:194
本文介绍了面试:我们可以实例化抽象类吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

面试官问 - 我们可以实例化一个抽象类吗?我说,不,他告诉我 - 错,我们可以。



我对此有点争论。然后他告诉我自己在你家里试试。

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

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

这里,我创建了我的类的实例,抽象类的调用方法。任何人都可以向我解释这个?

解决方案


这里,我正在创建我的类的实例


否,您不是在此处创建抽象类的实例。相反,您正在创建抽象类的匿名子类的实例。然后你正在调用抽象类引用指向子类对象的方法。



列在 JLS - 节#15.9.1 中: -


如果类实例创建表达式在类体中结束,那么
将被实例化的类是一个匿名类。然后:




  • 如果T表示类,则声明由T命名的类的匿名直接子类。如果T表示的
    类是最终类,那么它是编译时错误。

  • 如果T表示接口,那么实现接口的Object的匿名直接子类

  • >实例化的类是匿名子类。

p>

此外,在 JLS - Section#12.5 ,您可以了解对象创建过程。我会在这里引用一个语句: -


每当创建一个新的类实例时,内存空间被分配
它具有在类
中声明的所有实例变量的空间,以及在
类类型的每个超类中声明的所有实例变量,包括可以隐藏的所有实例变量。



在对新创建的对象的引用返回为
结果之前,使用以下过程处理指示的构造函数以初始化新的
对象: p>

您可以阅读我提供的链接的完整过程。






要实际看到实例化的类是一个匿名子类,你只需要编译两个类。假设您将这些类放在两个不同的文件中:



My.java

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

Poly.java

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

现在,编译两个源文件:

  javac My.java Poly.java 

现在在编译源代码的目录中,您将看到以下类文件:

  My.class 
Poly $ 1.class //对应于匿名子类的类文件
Poly.class

查看该类 - Poly $ 1.class 。这是由编译器创建的类文件对应于使用下面的代码实例化的匿名子类:

  new My(){} ; 

所以,很明显,有一个不同的类被实例化。



通常,类中的所有匿名子类都将以这种方式命名:

/ p>

  Poly $ 1.class,Poly $ 2.class,Poly $ 3.class等... 

这些数字表示这些匿名类在封闭类中出现的顺序。


The interviewer asked - Can we instantiate an abstract class? I said, No. He told me - Wrong, we can.

I argued a bit on this. Then he told me to try this yourself at your 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?

解决方案

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: -

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. It is a compile-time error if the class denoted by T is a final class.
  • If T denotes an interface, then an anonymous direct subclass of Object that implements the interface named by T is declared.
  • In either case, the body of the subclass is the ClassBody given in the class instance creation expression.
  • The class being instantiated is the anonymous subclass.

Emphasis mine.

Also, in JLS - Section # 12.5, you can read about the Object Creation Process. 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. Suppose you put those classes in two different files:

My.java:

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

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. 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.

这篇关于面试:我们可以实例化抽象类吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆