不得不提的知识点一 —— Java构造器的职能
Java对象是由构造器创建的吗?大多数人可能会回答是!但实际情况是:构造器只是负责对Java对象实例变量执行初始化(也就是赋初值),在执行构造器代码之前,该对象所占内存已经被分配下来,这些内存中存储的都是默认值,0、false或是null。
不得不提的知识点二 —— 静态代码块
当创建任何Java对象时,静态代码块总是会在对象初始化时进行初始化,在同一个JVM下,重复实例化多个Java对象,静态代码块只执行一次;如下面这段代码所示:
class Parent{
static{
System.out.println("Parent的静态代码块");
}
public Person(){
System.out.println("Parent的无参构造函数");
}
}
class Men extends Parent{
static{
System.out.println("Men的静态代码块");
}
public Men(){
System.out.println("Men的无参构造函数");
}
}
public class InitTest{
public static void main(String[] args){
new Men();
// new Men(); //再次调用实例化Men
}
}
输出结果为:
Parent的静态代码块
Men的静态代码块
Parent的无参构造函数
Men的无参构造函数
当在一次调用实例化Men时,输出结果为:
Parent的静态代码块
Men的静态代码块
Parent的无参构造函数
Men的无参构造函数
Parent的无参构造函数
Men的无参构造函数
细心的你,也许会发现,静态代码块出现的位置总是会出现在最上面,并且由父及子,这没什么奇怪的,我们之前已经说过了,静态代码块总是会在对象初始化时完成初始化。
有了这么一个前话,下面,我们的讲解将不再考虑静态初始化代码块的执行时间。
父类构造器
当创建任何Java对象时,程序总是会先依次调用父类非静态初始化块、父类构造器(总是从Object类开始)执行初始化,最后才调用本类的非静态初始化块、构造器执行初始化。这个调用时隐式进行的,也可以通过super进行显式调用。
- 关于super与this
子类构造器的第一行使用super()显示调用父类构造器的无参构造方法,也可写入参数,指定调用父类的有参构造方法;与super()相对的是this(),this()放在构造方法的第一行,用于显示调用本类的构造方法,同样可指定参数。由于super() 与 this() 只能放在构造器中且只能放在第一行,所以构造器中只能由super()或this()中的一个且在第一行。既没有super(),又没有this()的情况,将会隐式调用无参构造方法。
执行步骤如下;
1、执行Object类的非静态初始化(如果有的话)
2、隐式或显式调用Object类的一个或多个构造器执行初始化
3、执行Parent类的非静态初始化(如果有的话)
4、隐式或显式调用Parent类的一个或多个构造器执行初始化
5、执行Son类的非静态初始化块(如果有的话)
6、隐式或显式调用Son类的一个或多个构造器执行初始化
class Creature{
{
System.out.println("Creature的非静态初始化块");
}
public Creature() {
System.out.println("Creature无参构造器");
}
public Creature(String name) {
this();
System.out.println("Creature带有name参数的构造器,name参数:" + name);
}
}
class Animal extends Creature{
{
System.out.println("Animal的非静态初始化块");
}
public Animal(String name) {
super(name);
System.out.println("Animal带一个参数的构造器,name参数:" + name);
}
public Animal(String name, int age) {
this(name);
System.out.println("Animal带2个参数的构造器,age:" + age);
}
}
class Wolf extends Animal{
{
System.out.println("Wolf的非静态初始化块");
}
public Wolf() {
super("灰太狼", 3);
System.out.println("Wolf无参构造器");
}
public Wolf(double weight) {
this();
System.out.println("Wolf的带weight参数的构造器,weight:" + weight);
}
}
public class InitTest {
public static void main(String[] args) {
new Wolf(5.6);
}
}
运行结果
Creature的非静态初始化块
Creature无参构造器
Creature带有name参数的构造器,name参数:灰太狼
Animal的非静态初始化块
Animal带一个参数的构造器,name参数:灰太狼
Animal带2个参数的构造器,age:3
Wolf的非静态初始化块
Wolf无参构造器
Wolf的带weight参数的构造器,weight:5.6
访问子类对象的实例变量
子类方法可以访问父类的实例变量,这是因为子类继承父类就会获得父类的成员变量和方法,但父类的方法不能访问子类的实例变量,因为父类根本无法知道它将被哪个子类继承,它的子类将会增加怎样的成员变量
未完,待续…
所谓迷茫,就是你的才华还配不上你的梦想