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

    xiaoxiao2021-03-26  6

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

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

    转载请注明原文地址: https://ju.6miu.com/read-500171.html

    最新回复(0)