java类中方法和变量的定义顺序

一、在类的内部,变量定义的先后顺序决定了初始化的顺序。即使变量定义散布于方法定义之间,它们仍旧会在任何方法(包括构造器)被调用之前得到初始化。即:先变量后方法。
比如如下的java程序:

class Tag {
    Tag(int marker) {
        System.out.println("Tag(" + marker + ")");
    }
}
class Card {
    Tag t1 = new Tag(1); // Before constructor
    Card() {
        // Indicate we're in the constructor:
        System.out.println("Card()");
        t3 = new Tag(33); // Reinitialize t3
    }
    Tag t2 = new Tag(2); // After constructor
    void f() {
        System.out.println("f()");
    }
    Tag t3 = new Tag(3); // At end
}
public class OrderOfInitialization {
        public static void main(String[] args) {
        Card t = new Card();
        t.f(); // Shows that construction is done
    }
}

程序运行结果为:
Tag(1)
Tag(2)
Tag(3)
Card()
Tag(33)
f()

这个很简单,不多说。就是有一个地方需要注意,每次构造类的对象的时候,程序先跳到的是类的构造函数但是并不执行,然后跳到类中的第一个变量处执行。这个有什么区别,请先想一想,之后的列三会回答。

二、静态数据初始化,先静态,再非静态。

java程序如下:

class Bowl {
    Bowl(int marker) {
        System.out.println("Bowl(" + marker + ")");
    }
    void f(int marker) {
        System.out.println("f(" + marker + ")");
    }
}
class Table {
    static Bowl b1 = new Bowl(1);
    Table() {
        System.out.println("Table()");
        b2.f(1);
    }
    void f2(int marker) {
        System.out.println("f2(" + marker + ")");
    }
    static Bowl b2 = new Bowl(2);
}
class Cupboard {
    Bowl b3 = new Bowl(3);
    static Bowl b4 = new Bowl(4);
    Cupboard() {
        System.out.println("Cupboard()");
        b4.f(2);
    }
    void f3(int marker) {
        System.out.println("f3(" + marker + ")");
    }
    static Bowl b5 = new Bowl(5);
}
public class StaticInitialization { 
    public static void main(String[] args) {
        System.out.println("Creating new Cupboard() in main");
        new Cupboard();
        System.out.println("Creating new Cupboard() in main");
        new Cupboard();
        t2.f2(1);
        t3.f3(1);
    }
    static Table t2 = new Table();
    static Cupboard t3 = new Cupboard();
}

程序运行结果为:
Bowl(1)
Bowl(2)
Table()
f(1)
Bowl(4)
Bowl(5)
Bowl(3)
Cupboard()
f(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f(2)
f2(1)
f3(1)

这里需要注意的是静态变量只初始化一次。

三、构造器的调用顺序
1. 调用基类构造器。这个步骤会不断地反复递归下去,首先是构造这种层次结构的根,然后是下一层导出类,等等。直到最低层的导出类。
2. 按声明顺序调用成员的初始状态设置模块。
3. 调用导出类构造器的主体。

java程序如下:

class Meal {
    Meal() { 
        System.out.println("Meal()"); 
    }
}
class Bread {
    Bread() { 
        System.out.println("Bread()"); 
    }
}
class Cheese {
    Cheese() { 
        System.out.println("Cheese()"); 
    }
}
class Lettuce {
    Lettuce() { 
        System.out.println("Lettuce()"); 
    }
}
class Lunch extends Meal {
    Lunch() { 
        System.out.println("Lunch()"); 
    }
}
class PortableLunch extends Lunch {
    PortableLunch() { 
        System.out.println("PortableLunch()");
    }
}
public class Sandwich extends PortableLunch {
    private Bread b = new Bread();
    private Cheese c = new Cheese();
    private Lettuce l = new Lettuce();
    public Sandwich() {
        System.out.println("Sandwich()");
    }
    public static void main(String[] args) {
        new Sandwich();
    }
}

运行结果为:
Meal()
Lunch()
PortableLunch()
Bread()
Cheese()
Lettuce()
Sandwich()

这里有些同学就会有疑问了,对于主类为什么不是例一所说的先变量后方法,然后先输出
Bread()
Cheese()
Lettuce()
其实主类最先会执行main方法,然后main方法中生成一个Sandwich()对象。之后就是例一我所强调的,程序会先跳到主类对象的构造方法(不执行),然后发现主类是继承自PortableLunch()的子类,就会先构造PortableLunch(),即执行PortableLunch()的构造方法。同上,直到找到最初的基类Meal(),构造之。也就会先输出
Meal()
Lunch()
PortableLunch()
再进行先变量后方法,即输出
Bread()
Cheese()
Lettuce()
最后是主类对象的构造方法,输出
Sandwich()

四、在其他任何事物发生之前,将分配给对象的存储空间初始化成二进制的零。

java程序如下:

abstract class Glyph {
    abstract void draw();
    Glyph() {
        System.out.println("Glyph() before draw()");
        draw();
        System.out.println("Glyph() after draw()");
    }
}
class RoundGlyph extends Glyph {
    private int radius = 1;
    RoundGlyph(int r) {
        radius = r;
        System.out.println("RoundGlyph.RoundGlyph(), radius = " + radius);
    }
    void draw() {
        System.out.println("RoundGlyph.draw(), radius = " + radius);
    }
}
public class PolyConstructors {
    public static void main(String[] args) {
        new RoundGlyph(5);
    }
}

程序运行结果为:
Glyph() before draw()
RoundGlyph.draw(), radius = 0
Glyph() after draw()
RoundGlyph.RoundGlyph(), radius = 5

这个结果按前面的说的方法就很容易得出。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值