本文主要通过代码的实现,来研究下载Java中,继承的时候,父类和子类中代码的加载顺序。
一,无继承的时候:
首先我们先写几个类,其中类ClassA作为测试主体。
// 1,对象类,测试主体
public class ClassA {
// public static ClassA classa = new ClassA();
static{
System.out.println("ClassA的静态代码块A");
}
{
System.out.println("ClassA的构造代码块A");
}
public ClassA_Public_A classA_Public_A = new ClassA_Public_A();
private ClassA_Private_A classA_Private_A = new ClassA_Private_A();
public static ClassA_Static_A classA_Static_A = new ClassA_Static_A();
static public void methodA(){
System.out.println("ClassA的静态方法A");
}
static{
System.out.println("ClassA的静态代码块B");
}
{
System.out.println("ClassA的构造代码块B");
}
public ClassA_Public_B classA_Public_B = new ClassA_Public_B();
private ClassA_Private_B classA_Private_B = new ClassA_Private_B();
public static ClassA_Static_B classA_Static_B = new ClassA_Static_B();
static public void methodB(){
System.out.println("ClassA的静态方法B");
}
public ClassA(){
System.out.println("ClassA的构造方法");
}
public void excuteOveride(){
System.out.println("ClassA执行方法excuteOveride");
}
}
//2,作为私有变量使用
public class ClassA_Private_A {
public ClassA_Private_A(){
System.out.println("ClassA_Private私有变量A");
}
}
//3,作为私有变量使用
public class ClassA_Private_B {
public ClassA_Private_B(){
System.out.println("ClassA_Private私有变量B");
}
}
//4,作为公有变量使用
public class ClassA_Public_A {
public ClassA_Public_A(){
System.out.println("ClassA_Public公有变量A");
}
}
//5,作为公有变量使用
public class ClassA_Public_B {
public ClassA_Public_B(){
System.out.println("ClassA_Public公有变量B");
}
}
// 6,作为静态变量使用
public class ClassA_Static_A {
public ClassA_Static_A(){
System.out.println("ClassA_Static静态变量A");
}
}
// 7,作为静态变量使用
public class ClassA_Static_B {
public ClassA_Static_B(){
System.out.println("ClassA_Static静态变量B");
}
}
//8,测试入口类
public class ClassTest {
static {
System.out.println("Test的静态代码块");
}
{
System.out.println("Test构造代码块");
}
public ClassTest(){
System.out.println("Test无参构造方法");
}
public ClassTest(String name){
System.out.println("Test构造方法"+ name);
}
public static void main(String[] args) {
System.out.println("ClassTest执行main方法");
ClassA a = new ClassA();
a.excuteOveride();
}
private static void testMethod(){
System.out.println("ClassTest执行testMethod方法");
}
}
我们执行一下ClassTest类,执行结果如下:
--------------------------------------------------------
Test的静态代码块
ClassTest执行main方法
ClassA的静态代码块A
ClassA_Static静态变量A
ClassA的静态代码块B
ClassA_Static静态变量B
ClassA的构造代码块A
ClassA_Public公有变量A
ClassA_Private私有变量A
ClassA的构造代码块B
ClassA_Public公有变量B
ClassA_Private私有变量B
ClassA的构造方法
ClassA执行方法excuteOveride
--------------------------------------------------------
可以看到,无继承情况,在加载class时候,大原则是:
1,先执行静态代码,
2,其次执行普通代码,
3,然后才是构造函数。
再细划分,每一部分都是按照代码在类中出现的顺序进行先后执行的。
二,有继承的时候:
我们再添加几个类,其中,ClassB作为测试主体:
// 子类ClassB,继承ClassA,测试主体
public class ClassB extends ClassA {
static public void methodA(){
System.out.println("ClassB的静态方法A");
}
static{
System.out.println("ClassB的静态代码块A");
}
{
System.out.println("ClassB的构造代码块A");
}
public static ClassB_Static_A classB_Static_A = new ClassB_Static_A();
private ClassB_Private_A classB_Private_A = new ClassB_Private_A();
public ClassB_Public_A classB_Public_A = new ClassB_Public_A();
public ClassB(){
System.out.println("ClassB的构造方法");
}
static{
System.out.println("ClassB的静态代码块B");
}
{
System.out.println("ClassB的构造代码块B");
}
public static ClassB_Static_B classB_Static_B = new ClassB_Static_B();
private ClassB_Private_B classB_Private_B = new ClassB_Private_B();
public ClassB_Public_B classB_Public_B = new ClassB_Public_B();
public void excute(){
System.out.println("ClassB执行方法excute");
}
public void excuteOveride(){
System.out.println("ClassB执行方法excuteOveride");
}
static public void methodB(){
System.out.println("ClassB的静态方法B");
}
}
// 2 作为私有变量使用
public class ClassB_Private_A {
public ClassB_Private_A(){
System.out.println("ClassB_Private私有变量A");
}
}
// 3 作为私有变量使用
public class ClassB_Private_B {
public ClassB_Private_B(){
System.out.println("ClassB_Private私有变量B");
}
}
// 4 作为公有变量使用
public class ClassB_Public_A {
public ClassB_Public_A(){
System.out.println("ClassB_Public公有变量A");
}
}
// 5 作为公有变量使用
public class ClassB_Public_B {
public ClassB_Public_B(){
System.out.println("ClassB_Public公有变量B");
}
}
// 6 作为静态变量使用
public class ClassB_Static_A {
public ClassB_Static_A(){
System.out.println("ClassB_Static静态变量A");
}
}
// 7 作为静态变量使用
public class ClassB_Static_B {
public ClassB_Static_B(){
System.out.println("ClassB_Static静态变量B");
}
}
package com.oda.ai.controller.test;
// 8 测试入口类
public class ClassTest {
static {
System.out.println("Test的静态代码块");
}
{
System.out.println("Test构造代码块");
}
public ClassTest(){
System.out.println("Test无参构造方法");
}
public ClassTest(String name){
System.out.println("Test构造方法"+ name);
}
public static void main(String[] args) {
System.out.println("ClassTest执行main方法");
ClassB b = new ClassB();
b.excute();
b.excuteOveride();
}
private static void testMethod(){
System.out.println("ClassTest执行testMethod方法");
}
}
我们执行一下ClassTest类,执行结果如下:
--------------------------------------------------------
Test的静态代码块
ClassTest执行main方法
ClassA的静态代码块A
ClassA_Static静态变量A
ClassA的静态代码块B
ClassA_Static静态变量B
ClassB的静态代码块A
ClassB_Static静态变量A
ClassB的静态代码块B
ClassB_Static静态变量B
ClassA的构造代码块A
ClassA_Public公有变量A
ClassA_Private私有变量A
ClassA的构造代码块B
ClassA_Public公有变量B
ClassA_Private私有变量B
ClassA的构造方法
ClassB的构造代码块A
ClassB_Private私有变量A
ClassB_Public公有变量A
ClassB的构造代码块B
ClassB_Private私有变量B
ClassB_Public公有变量B
ClassB的构造方法
ClassB执行方法excute
ClassB执行方法excuteOveride
--------------------------------------------------------
可以看到,有继承情况,在加载class时候,大原则如下:
1,先执行父类静态代码。
2,其次执行子类静态代码。
3,再次是父类普通代码。
4,父类构造函数。
5,之后是子类普通代码。
6,最后子类构造函数。
同样,再细划分,每一部分都是按照代码在类中出现的顺序进行先后执行的。
同一部分中无论是变量还是代码块,都是按照代码出现在类中的先后顺序执行。
三,最后我们修改下测试入口类如下:
即不创建对象实例,直接调用类的静态方法:
//测试入口类
public class ClassTest {
static {
System.out.println("Test的静态代码块");
}
{
System.out.println("Test构造代码块");
}
public ClassTest(){
System.out.println("Test无参构造方法");
}
public ClassTest(String name){
System.out.println("Test构造方法"+ name);
}
public static void main(String[] args) {
System.out.println("ClassTest执行main方法");
ClassB.methodB();
}
private static void testMethod(){
System.out.println("ClassTest执行testMethod方法");
}
}
执行结果如下
--------------------------------------------------------
Test的静态代码块
ClassTest执行main方法
ClassA的静态代码块A
ClassA_Static静态变量A
ClassA的静态代码块B
ClassA_Static静态变量B
ClassB的静态代码块A
ClassB_Static静态变量A
ClassB的静态代码块B
ClassB_Static静态变量B
ClassB的静态方法B
--------------------------------------------------------
可以看到,再不创建实例的情况下,直接调用类的静态方法,
只是加载父类静态代码,和子类静态代码。