我们可以实例化一个抽象类吗?

本文翻译自: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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值