1:类初始化的顺序(废话不多说,直接看demo)
父类
/**
* 父类
*/
static class Father {
/**
* 姓名
*/
public String name = initName();
/**
* 年龄
*/
public static int age = initAge();
/**
* 初始化姓名
*
* @return 姓名
*/
private String initName() {
System.out.println(++order + " father init name");
return "father";
}
/**
* 初始化年龄
*
* @return 年龄
*/
private static int initAge() {
System.out.println(++order + " father init static age");
return 50;
}
// 构造代码块
{
System.out.println(++order + " father constructor code block");
}
// 静态代码块
static {
System.out.println(++order + " father static code block");
}
/**
* 构造方法
*/
public Father() {
System.out.println(++order + " father constructor getName = " + getName());
}
/**
* 获取姓名
*
* @return 姓名
*/
public String getName() {
return name;
}
}
子类
/**
* 子类
*/
static class Son extends Father {
/**
* 姓名
*/
public String name = initName();
/**
* 年龄
*/
public static int age = initAge();
/**
* 初始化姓名
*
* @return 姓名
*/
private String initName() {
System.out.println(++order + " son init name");
return "son";
}
/**
* 初始化年龄
*
* @return 年龄
*/
private static int initAge() {
System.out.println(++order + " son init static age");
return 20;
}
// 构造代码块
{
System.out.println(++order + " son constructor code block");
}
// 静态代码块
static {
System.out.println(++order + " son static code block");
}
/**
* 构造方法
*/
public Son() {
System.out.println(++order + " son constructor getName = " + getName());
}
/**
* 获取姓名
*
* @return 姓名
*/
@Override
public String getName() {
return name;
}
}
执行函数
/**
* 顺序
*/
private static int order = 0;
public static void main(String[] args) {
Father son = new Son();
}
父类和子类的代码基本一致,执行函数就只是创建一个子类。这段代码主要是探究类初始化过程中,构造方法,普通变量,静态变量,构造代码块和静态代码块的加载顺序,大家可以想想输出的结果是什么,下面我们来看结果
通过输出结果,可以得到结论
1:加载父类的静态变量和静态代码块(谁在前面先加载谁)
2:加载子类的静态变量和静态代码块(谁在前面先加载谁)
3:加载父类的普通变量和构造代码块(谁在前面先加载谁)
4:加载父类的构造方法
5:加载子类的普通变量和构造代码块(谁在前面先加载谁)
6:加载子类的构造方法
输出结果有一点比较有意思的是第6行,父类构造方法调用getName方法,输出结果为null,这里就涉及到多态了,因为getName方法调用到的其实是子类getName,但是这个时候子类的name变量还没被加载,所以为null
再看一个demo
/**
* 父类
*/
static class Father {
/**
* 姓名
*/
public static String name = "father";
// 静态代码块
static {
System.out.println("father init");
}
}
/**
* 子类1
*/
static class Son extends Father {
// 静态代码块
static {
System.out.println("son init");
}
}
public static void main(String[] args) {
System.out.println("Son1.name = " + Son.name);
}
输出:子类静态代码块竟然没有执行,是不是很诡异,这个是因为子类没有静态变量name,实际调用的是父类的静态变量,所以初始化的的时候,实际上就只是初始化父类
为了印证上面的说法,直接修改demo,给子类也添加一个静态变量name
/**
* 父类
*/
static class Father {
/**
* 姓名
*/
public static String name = "father";
// 静态代码块
static {
System.out.println("father init");
}
}
/**
* 子类1
*/
static class Son extends Father {
/**
* 姓名
*/
public static String name = "son";
// 静态代码块
static {
System.out.println("son init");
}
}
public static void main(String[] args) {
System.out.println("Son1.name = " + Son.name);
}
输出:可以看到这个时候子类的静态方法被执行了
2:多态的执行(废话不多说,直接看demo)
/**
* 父类
*/
static class Father {
/**
* 姓名
*/
public String name = "father";
/**
* 打印姓名1
*/
public void printName1() {
System.out.println("name = " + name);
}
/**
* 打印姓名2
*/
public void printName2() {
System.out.println("name = " + getName());
}
/**
* 获取姓名
*
* @return 姓名
*/
public String getName() {
return name;
}
}
/**
* 子类1
*/
static class Son1 extends Father {
/**
* 姓名
*/
public String name = "son1";
/**
* 打印姓名1
*/
@Override
public void printName1() {
System.out.println("name = " + name);
}
/**
* 打印姓名2
*/
@Override
public void printName2() {
System.out.println("name = " + getName());
}
/**
* 获取姓名
*
* @return 姓名
*/
@Override
public String getName() {
return name;
}
}
/**
* 子类2
*/
static class Son2 extends Father {
/**
* 姓名
*/
public String name = "son2";
/**
* 获取姓名
*
* @return 姓名
*/
@Override
public String getName() {
return name;
}
}
public static void main(String[] args) {
Father son1 = new Son1();
son1.printName1();
son1.printName2();
System.out.println("-------------");
Father son2 = new Son2();
son2.printName1();
son2.printName2();
}
输出:编译看左边,运行看右边,所以实际执行都是子类的方法,其中son1重写了printName1和printName2,所以执行的都是重写的方法。son2没有对printName1和printName2进行重写,这个时候printName1调用的是父类方法,printName2调用的是父类方法打印getName方法的结果,但是因为子类有重写getName,所以打印的其实是子类getName的返回结果
再看一个demo
/**
* 父类
*/
static class Father {
/**
* 打印姓名
*
* @param obj 参数
*/
public void printName(Object obj) {
System.out.println("father printName obj " + obj);
}
/**
* 打印姓名
*
* @param str 参数
*/
private void printName(String str) {
System.out.println("father printName str " + str);
}
}
/**
* 子类
*/
static class Son extends Father {
/**
* 打印姓名
*
* @param obj 参数
*/
@Override
public void printName(Object obj) {
System.out.println("son printName obj " + obj);
}
}
public static void main(String[] args) {
Father son = new Son();
son.printName("爸爸");
System.out.println("-----------");
new Son().printName("儿子");
}
输出:第一个printName调用的是父类的私有方法,该方法是重载方法,结果说明运行看右边,只针对子类可以继承到的方法