-
大家在去参加面试的时候,经常会遇到这样的考题:给你两个类的代码,它们之间是继承的关系,每个类
里只有构造器方法和一些变量,构造器里可能还有一段代码对变量值进行了某种运算,另外还有一些将变
量值输出到控制台的代码,然后让我们判断输出的结果。这实际上是在考查我们对于继承情况下类的初始
化顺序的了解。
我们大家都知道,对于静态变量、静态初始化 块、变量、初始化块、构造器,它们的初始化顺序以此是静
态变量
>
静态初始化块>
变量
>
初始化块
>
构造器。我们也可以通过下面的测试代码来 验证这一点:
Java
代码
public class InitialOrderT
est {
//
静态变量
public static String staticField =
静态变量
//
变量
public String field =
变量
//
静态初始化块
static {
n(staticField);
n(
静态初始化块
}
//
初始化块
{
n(field);
n(
初始化块
}
//
构造器
public InitialOrderTest() {
n(
构造器
}
public static void main(String[] args) {
new InitialOrderTest();
}
}
public class InitialOrderT
est {
//
静态变量
public static String staticField =
静态变量
//
变量
public String field =
变量
//
静态初始化块
static {
n(staticField);
n(
静态初始化块
}
//
初始化块
{
n(field);
n(
初始化块
}
//
构造器
public InitialOrderTest() {
n(
构造器
}
public static void main(String[] args) {
new InitialOrderTest();
}
}
运行以上代码,我们会得到如下的输出结果:
静态变量
静态初始化块
变量
初始化块
构造器
这 与上文中说的完全符合。那么对于继承情况下又会怎样呢?我们仍然以一段测试代码来获取最终结果:
Java
代码
class Parent {
//
静态变量
public static String p_StaticField =
父类
--
静态变量
//
变量
public String p_Field =
父类
--
变量
//
静态初始化块
static {
n(p_StaticField);
n(
父类
--
静态初始化块
}
//
初始化块
{
n(p_Field);
n(
父类
--
初始化块
}
//
构造器
public Parent() {
n(
父类
--
构造器
}
}
public class SubClass extends Parent {
//
静态变量
public static String s_StaticField =
子类
--
静态变量
//
变量
public String s_Field =
子类
--
变量
//
静态初始化块
static {
n(s_StaticField);
n(
子类
--
静态初始化块
}
//
初始化块
{
n(s_Field);
n(
子类
--
初始化块
}
//
构造器
public SubClass() {
n(
子类
--
构造器
}
//
程序入口
public static void main(String[] args) {
new SubClass();
}
}
class Parent {
//
静态变量
public static String p_StaticField =
父类
--
静态变量
//
变量
public String p_Field =
父类
--
变量
//
静态初始化块
static {
n(p_StaticField);
n(
父类
--
静态初始化块
}
//
初始化块
{
n(p_Field);
n(
父类
--
初始化块
}
//
构造器
public Parent() {
n(
父类
--
构造器
}
}
public class SubClass extends Parent {
//
静态变量
public static String s_StaticField =
子类
--
静态变量
//
变量
public String s_Field =
子类
--
变量
//
静态初始化块
static {
n(s_StaticField);
n(
子类
--
静态初始化块
}
//
初始化块
{
n(s_Field);
n(
子类
--
初始化块
}
//
构造器
public SubClass() {
n(
子类
--
构造器
}
//
程序入口
public static void main(String[] args) {
new SubClass();
}
}
运行一下上面的代码,结果马上呈现在我们的眼前:
父类
--
静态变量
或
父类
--
静态初始化块
子类
--
静态变量
或
子类
--
静态初始化块
父类
--
变量
父类
--
初始化块
父类
--
构造器
子类
--
变量
子类
--
初始化块
子类
--
构造器
现在,结果已经不言自明了 。大家可能会注意到一点,那就是,并不是父类完全初始化完毕后才进行子类
的初始化,实际上子类的静 态变量和静态初始化块的初始化是在父类的变量、初始化块和构造器初始化之
前就完成了。
静态变量和静态初始化块根据在类中定义的顺序执行!
!
分析如下程序类初始化过程:
例子
1
:
class Insect{
private int i=9;
protected int j;
Insect(){
n(
j=37;
}
private static int x1=print(
static int print(String s)
{
n(s);
return 47;
}
}
public class Bettle extends Insect{
private int k=print(
public Bettle(){
n(
n(
}
private static int x2=print(
public static void main(String [] args)
{
n(
Bettle b=new Bettle();
}
}
运行结果:
static lized
static Insect.x2 initialized
Bettle constructor
i=9,j=0
Bettle.k initialized
k=47
j=37
static
成员在
Beetle
构造器还没有调用时就加载
Bettle
运行这个就先加载父类
,
即加载
Inse ct
,
在加载
Insect
先运行所有的
Static
代码
(函
数建立,但不运行)
,运行下面这一句
private static int x1=print(
加载完成后加载
Bettle
然后进入
Main()
,运行
n(
再运行
Bettle b=new Bettle();
新建时加新建父类,加载类时,先把所有属性设为初始值
(
string
为空串,数字为
0
)
,
如果你定义了值,再赋值,如
private int i=9;
然后运行构造函数
n(
加载完父类再加载子类
同上,先设定义值
private int k=print(
然后运行构造函数
例子
2
:
/**
* @author
潘宝坤
panbaokun@
* @version 1.0
创建时间:
2006-11-23
下午
02:49:16
*
类说明
*
父类初始化时会调用子类的重载的函数
*
* jvm
先加载类对象,再实例化对象.
*
类级别的东西先加载.
*
所以初始化的顺序是:
先父类静态后子类静态;先父类定义初始化
*
父类构造函数初始化,再子类定义初始化,再子类构造函数初始化
*
如果在初始化时父类调用了父类中被子类重载的方法,那么执行的是子类的方法.
*
所以要注意
:
不要在定义初始化时调用函数,这样不安全
,因为无法预知子类重载的方法
-
-
-
-
-
-
-
-
本文更新与1970-01-01 08:00,由作者提供,不代表本网站立场,转载请注明出处:https://www.bjmy2z.cn/gaokao/553582.html
-
上一篇:没有了
下一篇:没有了