Rav*_*avi 561 java oop class object abstract
采访者问:我们可以实例化一个抽象类吗?我说,不,他告诉我 - 错,我们可以.
我对此有点争论.然后他告诉我自己在家里试试.
abstract class my {
public void mymethod() {
System.out.print("Abstract");
}
}
class poly {
public static void main(String a[]) {
my m = new my() {};
m.mymethod();
}
}
Run Code Online (Sandbox Code Playgroud)
在这里,我正在创建我的类的实例并调用抽象类的方法.有人可以向我解释一下吗?在我的采访中我真的错了吗?
Roh*_*ain 707
在这里,我正在创建我的班级实例
不,您不是在这里创建抽象类的实例.而是在创建抽象类的匿名子类的实例.然后,您在指向子类对象的抽象类引用上调用该方法.
JLS中明确列出了此行为- 第15.9.1节: -
如果类实例创建表达式在类主体中结束,则实例化的类是匿名类.然后:
- 如果T表示一个类,则声明由T命名的类的匿名直接子类.如果由T表示的类是最终类,则是编译时错误.
- 如果T表示接口,则声明实现由T命名的接口的Object的匿名直接子类.
- 在任何一种情况下,子类的主体都是类实例创建表达式中给出的ClassBody.
- 被实例化的类是匿名子类.
强调我的.
此外,在JLS - Section#12.5中,您可以阅读有关对象创建过程的信息.我在这里引用一句话: -
每当创建一个新的类实例时,就会为它分配内存空间,为类类型中声明的所有实例变量提供空间,并在类类型的每个超类中声明所有实例变量,包括可能隐藏的所有实例变量.
在作为结果返回对新创建的对象的引用之前,处理指示的构造函数以使用以下过程初始化新对象:
您可以在我提供的链接上阅读有关完整程序的信息.
实际上,要实例化的类是Anonymous SubClass,您只需要编译两个类.假设您将这些类放在两个不同的文件中:
My.java:
abstract class My {
public void myMethod() {
System.out.print("Abstract");
}
}
Run Code Online (Sandbox Code Playgroud)
Poly.java:
class Poly extends My {
public static void main(String a[]) {
My m = new My() {};
m.myMethod();
}
}
Run Code Online (Sandbox Code Playgroud)
现在,编译两个源文件:
javac My.java Poly.java
Run Code Online (Sandbox Code Playgroud)
现在,在编译源代码的目录中,您将看到以下类文件:
My.class
Poly$1.class // Class file corresponding to anonymous subclass
Poly.class
Run Code Online (Sandbox Code Playgroud)
看那个班 - Poly$1.class.它是由编译器创建的类文件,对应于您使用以下代码实例化的匿名子类:
new My() {};
Run Code Online (Sandbox Code Playgroud)
因此,很明显有一个不同的类被实例化.就是这样,只有在编译器编译之后,该类才会被赋予名称.
通常,类中的所有匿名子类都将以这种方式命名:
Poly$1.class, Poly$2.class, Poly$3.class, ... so on
Run Code Online (Sandbox Code Playgroud)
这些数字表示这些匿名类在封闭类中出现的顺序.
JB *_*zet 88
上面实例化了一个匿名内部类,它是my抽象类的子类.它并不完全等同于实例化抽象类本身.OTOH,每个子类实例都是其所有超类和接口的实例,因此大多数抽象类确实通过实例化其中一个具体子类来实例化.
如果面试官只是说"错!" 虽然没有解释,并且举了这个例子,作为一个独特的反例,我认为他不知道他在说什么.
nce*_*rar 30
只是你可以做出的观察:
poly扩展my?这没用......my.class,poly.class和poly$1.class我们可以实例化一个抽象类吗?
不,我们不能.我们可以做的是,创建一个匿名类(这是第三个文件)并实例化它.
超类实例化怎么样?
抽象超类不是由我们实例化的,而是由java 实例化的.
编辑:请他测试一下
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());
}
Run Code Online (Sandbox Code Playgroud)
输出是:
false
class my$1
class my$2
Run Code Online (Sandbox Code Playgroud)
小智 18
您只需一行即可轻松回答问题
不,你永远不能实例抽象类
但是,面试官仍然不同意,那么你可以告诉他/她
你所能做的就是,你可以创建一个匿名类.
并且,根据Anonymous类,类声明并在同一位置/行实例化
因此,面试官可能有兴趣检查您的置信水平以及您对OOP的了解程度.
Gle*_*est 11
技术答案
抽象类无法实例化 - 这是定义和设计.
来自JLS,第8章.类:
命名类可以声明为abstract(第8.1.1.1节),如果未完全实现,则必须声明为abstract; 这样的类不能实例化,但可以通过子类扩展.
来自JSE 6的Java doc for Classes.newInstance():
InstantiationException - 如果此Class表示抽象类,接口,数组类,基元类型或void; 或者如果该类没有无效的构造函数; 或者如果实例化因某些其他原因而失败.
当然,您可以实例化抽象类的具体子类(包括匿名子类),并且还可以对抽象类型的对象引用进行类型转换.
不同的角度 - Teamplay和社交智能:
当我们处理复杂的技术和法律规范时,这种技术上的误解在现实世界中经常发生.
"人员技能"在这里比"技术技能"更重要.如果竞争激烈并且积极地试图证明你的观点,那么理论上你可能是正确的,但你也可以在战斗/破坏"面子"/创造一个敌人而不是它的价值时做更多的伤害.在解决分歧方面需要和解和理解.谁知道 - 也许你是"两个都正确"但是对于条款的工作方式略有不同?
谁知道 - 尽管不太可能,面试官有可能故意引入一个小冲突/误解,让你陷入困境,看看你的情绪和社交行为.与同事保持亲切和建设性,遵循老年人的建议,并在面试结束后通过电子邮件或电话解决任何挑战/误解.表明你是有动力和注重细节的.
这是一个公认的事实,abstract class可以不为大家回答被实例化.
当程序定义匿名类时,编译器实际上创建了一个具有不同名称的新类(具有模式EnclosedClassName$n,其中n是匿名类号)
因此,如果您反编译此Java类,您将找到如下代码:
我的课
abstract class my {
public void mymethod()
{
System.out.print("Abstract");
}
}
Run Code Online (Sandbox Code Playgroud)
poly $ 1.class(生成的"匿名类"类)
class poly$1 extends my
{
}
Run Code Online (Sandbox Code Playgroud)
ploly.cass
public class poly extends my
{
public static void main(String[] a)
{
my m = new poly.1(); // instance of poly.1 class NOT the abstract my class
m.mymethod();
}
}
Run Code Online (Sandbox Code Playgroud)
关于抽象类
抽象类的目的是表现得像基类。在继承层次结构中,您将看到位于顶部的抽象类。
| 归档时间: |
|
| 查看次数: |
228205 次 |
| 最近记录: |