An article on classloading表示不应在构造函数中调用方法getClass()
,因为:
对象初始化仅在出口处完成 构造函数代码。
他们给出的例子是:
public class MyClassLoader extends ClassLoader{
public MyClassLoader(){
super(getClass().getClassLoader()); // should not call getClass() because object
// initialization will be complete only at
// the exit of the constructor code.
}
}
但据我所知,本机最终方法getClass()
将始终返回该对象实例的java.lang.Class
对象,而不管其中被调用(在构造函数内或不)。
在构造函数中调用getClass()
会给我们带来问题吗?
如果是这样,在构造函数中调用getClass()
会给我们带来错误的一些例子是什么?
答案 0 :(得分:10)
在构造函数中调用getClass()会给我们带来问题吗? 如果是这样,在构造函数中调用getClass()的示例是什么 给我们错误?
以这种方式在构造函数中使用getClass()
将始终导致编译错误,因为在this
被调用之前无法引用super()
。
Main.java:17: error: cannot reference this before supertype constructor has been called
super(getClass().getClassLoader()); // should not call getClass() because object
^
1 error
您可以在http://ideone.com/B0nYZ1上自行测试。
Class
已准备就绪,但实例尚未用于引用Class
。
尽管如此,你可以在构造函数中使用Class
引用,但你必须以稍微不同的方式执行:super(MyClassLoader.class.getClassLoader())
此外,在调用超类型构造函数之后,您可以在构造函数中自由使用getClass()
- 正如您已经指出的那样,该对象基本上已准备就绪并且{{ 1}}引用可以从实例中推断出来。
答案 1 :(得分:1)
至少在super()调用中你不应该调用父类方法的原因是,由于尚未构建父对象,因此无法知道方法是否能正确运行。你必须记住,调用是在父构造函数有机会准备它的数据之前发生的。
在super()调用之后,在合理范围内使用父方法应该是相当安全的,因为父对象已经完成了他们需要被认为可以使用的所有内容。我在合理范围内看到,因为父方法可能会调用覆盖子方法,您必须确保在构造期间可以安全地调用它们。
不安全:
public static class Base {
public final void print() {
System.out.println( this.get() );
}
public int get() {
return 2;
}
}
public static final class Sub extends Base {
private int x;
public Sub() {
super();
this.print();
this.x = 1;
}
public int get() {
return this.x;
}
}
安全:
public static class Base {
public final void print() {
System.out.println( this.get() );
}
public int get() {
return 2;
}
}
public static final class Sub extends Base {
private int x;
public Sub() {
super();
this.x = 1;
this.print();
}
public int get() {
return this.x;
}
}
编辑 - 编辑: 在重试以下代码并调用getClass()之后,它实际上没有编译。因此,完全忽略先前关于Object.getClass()的语句是在父初始化之前调用的唯一可用方法。我不知道如何错过,我很抱歉任何混乱。
答案 2 :(得分:1)
$ javac whose/MyClassLoader.java
whose/MyClassLoader.java:5: error: cannot reference this before supertype constructor has been called
super(getClass().getClassLoader());
^
1 error
我知道现在已经很晚了。