带块的Java类实例化
我有一个这样的基类带块的Java类实例化,java,instantiation,Java,Instantiation,我有一个这样的基类 abstract class BaseClass { protected Class<? extends iBase> _BASE = null; protected static abstract class iBase {} protected BaseClass() { setBase(); } protected void setBase() { // use reflectio
abstract class BaseClass {
protected Class<? extends iBase> _BASE = null;
protected static abstract class iBase {}
protected BaseClass() {
setBase();
}
protected void setBase() {
// use reflection to find fields, but...
// _BASE is null?
}
}
public class MyClass extends BaseClass {
{ // what is this called? Anonymous Block Class Statements?
_BASE = iBase.class;
} // does this get called before constructor starts?
public static class iBase extends BaseClass.iBase { // yes, it is hiding super
public static final String someValue = "";
}
public MyClass() {
super();
}
}
当我去实例化新类时
MyClass myClass = new MyClass();
\u BASE
为空,为什么?我清楚地设置了它,因为超类构造函数在子类构造函数之前被称为。因此,在子类中的块初始化基之前执行setBase()
从基类构造函数调用可重写方法是您应该避免的事情,这正是因为您在该实践中面临的问题。还因为如果在子类中重写它,则重写的实现将在尚未正确初始化的对象上调用。因为在子类构造函数之前调用了超类构造函数。因此,在子类中的块初始化基之前执行
setBase()
从基类构造函数调用可重写方法是您应该避免的事情,这正是因为您在该实践中面临的问题。还有一个原因是,如果在子类中重写它,则重写的实现将在尚未正确初始化的对象上调用。调试没有显示这一点;它显示设置了_BASE,然后是单步执行时执行的方法。然后是调试器错误,或者您没有正确解释它的功能。只要到处添加println语句,您就会看到(如果_BASE为null的事实不足以说服您);它显示设置了_BASE,然后是单步执行时执行的方法。然后是调试器错误,或者您没有正确解释它的功能。只要到处添加println语句,您就会看到(如果_BASE为null这一事实不足以说服您)。您可以将该类作为参数传递给
BaseClass
构造函数//这叫什么?匿名块类语句?-这些是实例(与静态相反)初始化blocks@Dici因为通过反射,我可以得到子类的字段,因为父类不设置,但是你的字段在父类上。。。访问它不需要反射。不管怎么说,我不知道你想达到什么目的。顺便说一句,在构造函数中调用的可重写方法是糟糕且危险的做法。这就是为什么超类的构造函数总是在其子类的构造函数之前被调用的原因。子类不一定知道超类持有的所有状态,因此在正确初始化超类字段之前,它不应该执行任何代码。从构造函数调用的可重写方法是子类在初始化完成之前向其超类构造函数中注入代码的网关。这就是为什么它很危险。您可以将该类作为参数传递给BaseClass
构造函数//这叫什么?匿名块类语句?-这些是实例(与静态相反)初始化blocks@Dici因为通过反射,我可以得到子类的字段,因为父类不设置,但是你的字段在父类上。。。访问它不需要反射。不管怎么说,我不知道你想达到什么目的。顺便说一句,在构造函数中调用的可重写方法是糟糕且危险的做法。这就是为什么超类的构造函数总是在其子类的构造函数之前被调用的原因。子类不一定知道超类持有的所有状态,因此在正确初始化超类字段之前,它不应该执行任何代码。从构造函数调用的可重写方法是子类在初始化完成之前向其超类构造函数中注入代码的网关。这就是为什么它很危险。