java 构造器(constructor)
构造器访问权限
public:所有的类都可以使用;
protected: 本包以及子类可以使用;
default:本包可以使用;
private:仅本类可以使用。
一.默认构造器:
构建过程是从基类向外扩散的,所以基类在导出类可以访问它之前,就已经完成了初始化
package ch7_05; class A{ public A(){ System.out.println("I am A"); } } class B{ public B(){ System.out.println("I am B"); } } public class C extends A{ B b = new B(); public static void main(String[] args) { new C(); } }/* output:
I am A
I am B
*///~
二.带参数构造器
默认构造器编译器可以轻松调用它是因为不必考虑要传递什么样的参数的问题,但是如果没有默认的基类构造器,或者想调用一个带参数的基类构造器,就必须用关键字super显式地编写调用基类构造器的语句,并且配之以适当的参数
package object; import static net.mindview.util.Print.*; class Game{ Game(int i) { print("Game constructor"); } } class BoardGame extends Game{ BoardGame(int i) { super(i); //必须在构造器的第一行 super must consructor's first row print("BoardGame constructor"); } } public class Chess extends BoardGame{ Chess() { super(1); //如果基类有默认构造器,导出类一定要用super()在第一行显示的调用基类的带参构造器 print("Chess constructor"); } public static void main(String[] args) { Chess x = new Chess(); } }/* output: Game constructor BoardGame constructor Chess constructor *///~
三.构造器的调用顺序,基类的构造器总是在导出类的构造过程中被调用,而且按照继承层次逐渐向上链接,以使每个基类的构造器都能得到调用,(第九章多态)
1.调用基类构造器,这个步骤会不断重复执行下去,首先是构造这种层次结构的根,然后是下一层导出类,等等,直到最底层的导出类(在任何其它事务发生之前,将分配给对象的存储空间初始化为二进制的零
2.按声明顺序调用成员的初始化方法
3.调用导出类构造器的主体
package object; //: polymorphsim/Sandwich.java // Order of constructor call import static net.mindview.util.Print.*; class Meal{ Meal(){print("meal");} } class Bread{ Bread(){print("bread");} } class Cheese{ Cheese(){print("CZheese");} } class Lettuce extends Meal{ Lettuce(){print("Lettuce");} } class Lunch extends Meal{ Lunch(){print("Lunch");} } class PortableLunch extends Lunch{ PortableLunch(){print("PortableLunch");} } public class Sandwich extends PortableLunch{ private Bread b = new Bread(); private Cheese c = new Cheese(); private Lettuce l =new Lettuce(); public Sandwich(){print("sandwich");} public static void main(String[] args) { new Sandwich(); } }/* output: meal Lunch PortableLunch bread CZheese meal Lettuce sandwich *///:~
四.构造器内部的多态行为
1.如果在构造器内部调用了正在构造的对象的某个动态绑定方法,那么该动态方法就会在正在构造对象还未初始化之前就会被调用,这肯定会招致灾难,所以在构造器内唯一能够安全调用的那些方法是基类的final方法(也适用于private,它们自动属于final方法),这些方法不能被覆盖,也就不会出现问题.
//polymorphism/Polyconstructors.java //constructors and poly morphism //don't produce what you mght expect package object; class Glyph{ void draw() { System.out.println("ZGlyph.draw()"); } Glyph() { System.out.println("Glyph() before draw()"); draw(); //在导出类RoundGlyph还未初始化之前就调用了RoudnGlyph.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); } }/* output: Glyph() before draw() Roundglyph.draw(), radius = 0 //在导出类RoundGlyph还未初始化之前就调用了RoudnGlyph.draw()方法,radius不是1 Glyph() after draw() roundglyph..roundglyph(), radius = 5 *///:~