1、问题的发现
最近在进行数据库方面的编码时,无意间发现了一个报错信息,“Cannot reference XXX before supertype constructor has been called”。意思很明显,在父类构函数初始化之前不能引用这个变量。当把这个变量加上startic修饰符时,就不再报错。
2、猜想验证
那么为什么加上static修饰后,就不再报错了呢?很显然,与Java的初始化顺序有关。因此,Coder哥编写了一个验证Java初始化顺序的验证代码
public
class
Base {
static
String sVar = getString(
"父类静态变量初始化"
);
public
String
var
= getString(
"父类非静态变量初始化"
);
static
{
System.
out
.println(
"父类的静态初始化块"
);
System.
out
.println(
"父类的非静态初始化块"
);
public
Base
() {
System.
out
.println(
"父类构造函数 start"
);
draw(
"父类调用draw方法"
);
System.
out
.println(
"父类构造函数 end"
);
static
String getString(String
base
) {
System.
out
.println(
base
);
return
base
;
public
void
draw
(String
string
) {
System.
out
.println(
string
);
public
class
SubClass
extends
Base
{
public
String var = getString(
"子类初始化非静态变量"
);
private
String subVar = getString(
"子类初始化私有变量"
);
static
String superVar = getString(
"子类初始化静态变量"
);
static
{
System.out.println(
"子类的静态初始化块"
);
System.out.println(
"子类的非静态初始化块"
);
SubClass() {
System.out.println(
"子类构造函数start"
);
draw(
"子类调用draw方法"
);
System.out.println(
"子类构造函数end"
);
public
void
draw
(String string) {
System.out.println(string + subVar);
public
static
void
main
(String[] args) {
new
SubClass();
运行程序后,得到的结果如下:
父类静态变量初始化
父类的静态初始化块
子类初始化静态变量
子类的静态初始化块
父类非静态变量初始化
父类的非静态初始化块
父类构造函数 start
父类调用draw方法 null
父类构造函数 end
子类初始化非静态变量
子类初始化私有变量
子类的非静态初始化块
子类构造函数 start
子类调用draw方法子类初始化私有变量
子类构造函数 end
3、结果分析
由此结果,我们便可以清楚的看出文章开头那个错误的原因:父类构造函数初始化早于子类非静态变量的初始化,晚于子类静态变量的初始化。所以,当我们把变量改为静态修饰时,不会再报错了。大家可以自己动手亲自试验一下Java的初始化过程,在以后的编程中会有很大的用处。
最近在进行数据库方面的编码时,无意间发现了一个报错信息,“Cannot reference XXX before supertype constructor has been called”。意思很明显,在父类构函数初始化之前不能引用这个变量。当把这个变量加上startic修饰符时,就不再报错。那么为什么加上static修饰后,就不再报错了呢?很显然,与Java的初始化顺序有关。因此,Coder哥编
英文的真实描述为:“typename
cannot
be used outside a template declaration”,由于翻译错误,将 typename 翻译成了 类型名称
解决办法:
根据错误指示的行数, 删除即可
typename除用在模板声明中外,只能用于说明模板类的成员是一个类型.
template class X {};
// Another wa...
public static void main(String[] args) {
Test1 test1 = new Test1();
System.out.println(test1.a);
在上面的代码中,通过使用 "
SuperType
.call(this)" 来调用
SuperType
函数。其中 "this" 是指 SubType 函数的实例。
这样做可以让 SubType 函数继承
SuperType
函数中的属性和方法。
当你创建 s1 和 s2 两个新的 SubType 实例时, 都会调用一次
SuperType
() 方法,并将 this 传递给它