先来看一下下面这段代码,此段代码转载于:http://www.jb51.net/article/37881.htm
class Parent {
// 静态变量
public static String p_StaticField = "父类--静态变量";
// 变量(其实这用对象更好能体同这一点,如专门写一个类的实例)
//如果这个变量放在初始化块的后面,是会报错的,因为你根本没有被初始化
public String p_Field = "父类--变量";
// 静态初始化块
static {
System.out.println(p_StaticField);
System.out.println("父类--静态初始化块");
}
// 初始化块
{
System.out.println(p_Field);
System.out.println("父类--初始化块");
}
// 构造器
public Parent() {
System.out.println("父类--构造器");
}
}
public class SubClass extends Parent {
// 静态变量
public static String s_StaticField = "子类--静态变量";
// 变量
public String s_Field = "子类--变量";
// 静态初始化块
static {
System.out.println(s_StaticField);
System.out.println("子类--静态初始化块");
}
// 初始化块
{
System.out.println(s_Field);
System.out.println("子类--初始化块");
}
// 构造器
public SubClass() {
//super();
System.out.println("子类--构造器");
}
// 程序入口
public static void main(String[] args) {
System.out.println("*************in main***************");
new SubClass();
System.out.println("*************second subClass***************");
new SubClass();
}
}
代码的执行结果如下:
父类--静态变量
父类--静态初始化块
子类--静态变量
子类--静态初始化块
*************in main***************
父类--变量
父类--初始化块
父类--构造器
子类--变量
子类--初始化块
子类--构造器
*************second subClass***************
父类--变量
父类--初始化块
父类--构造器
子类--变量
子类--初始化块
子类--构造器
在这段代码中,子类和父类中都有static变量和static代码块,父类中有无参的构造方法,从上面执行的结果可以得出下面结论:
1、当代码进入到子类的main方法时,此时不执行main()方法中的任何语句,这时候会先开始按顺序先加载父类的static变量、static代码块,再加载子类的static变量、static代码块;
2、当父类和子类的static变量和代码块加载完之后,开始按顺序执行main方法中的语句System.out.println("*************in main***************");;
3、执行完println语句之后,此时new一个子类对象,由于子类继承父类,此时会先按顺序初试化父类中的变量、代码块、构造方法,然后再初始化子类变量、代码块、构造方法。其中变量最先初始化创建,其次是代码块,构造方法最后创建;
4、当new完一个子类对象之后,再new第二个子类对象时,由于static变量与方法还有代码块在内存中只加载一遍,此时父类和子类已经加载了一遍,所以不会再次加载
5、当把子类main方法中的代码都删掉
System.out.println("*************in main***************");
new Super_Sub_Contr();
System.out.println("*************second subClass***************");
new Super_Sub_Contr();
此时执行程序,子类和父类的static变量和代码块也还是会加载,但是其它的变量、代码块、构造方法都不会加载。
以上代码是在子类里面直接new子类对象,如果我们新建一个类,在这个类中new子类结果会是怎样?还有,当我们初始化变量时,变量调用了一个方法,这个方法会不会在变量初始时就执行?看看下面代码执行的结果:
class Parent {
// 静态变量
public static String p_StaticField = "父类--静态变量";
// 变量(其实这用对象更好能体同这一点,如专门写一个类的实例)
// 如果这个变量放在初始化块的后面,是会报错的,因为你根本没有被初始化
public String p_Field = "父类--变量";
int a = getParent();
// 静态初始化块
static {
System.out.println(p_StaticField);
System.out.println("父类--静态初始化块");
}
// 初始化块
{
System.out.println(p_Field);
System.out.println("父类--初始化块");
}
{
System.out.println(a);
}
// 构造器
public Parent() {
System.out.println("父类--构造器");
}
private int getParent() {
System.out.println("********getParent()*********");
return 6;
}
}
class SubClass extends Parent {
// 静态变量
public static String s_StaticField = "子类--静态变量";
// 变量
public String s_Field = "子类--变量";
// 静态初始化块
static {
System.out.println(s_StaticField);
System.out.println("子类--静态初始化块");
}
// 初始化块
{
System.out.println(s_Field);
System.out.println("子类--初始化块");
}
// 构造器
public SubClass() {
// super();
System.out.println("子类--构造器");
}
}
public class Super_Sub_Contr{
// 程序入口
public static void main(String[] args) {
System.out.println("*************in main***************");
new SubClass();
System.out.println("*************second subClass***************");
new SubClass();
}
}
代码执行结果
*************in main***************
父类--静态变量
父类--静态初始化块
子类--静态变量
子类--静态初始化块
********getParent()*********
父类--变量
父类--初始化块
6
父类--构造器
子类--变量
子类--初始化块
子类--构造器
*************second subClass***************
********getParent()*********
父类--变量
父类--初始化块
6
父类--构造器
子类--变量
子类--初始化块
子类--构造器
从结果可知:
1、当在另外一个类中new子类时,会先打印:*************in main***************
这是因为在子类中new子类,此时子类还没有开始加载,所以当子类加载完后才能执行main方法;
2、当初试化变量中调用了另一个方法时,会先执行这个方法完成变量的初始化,然后再初始化代码块;
以上代码还没有涉及到子类和父类有多个构造函数,构造函数之间重载的问题,可以看看下面代码:
class Parent {
// 静态变量
public static String p_StaticField = "父类--静态变量";
// 变量(其实这用对象更好能体同这一点,如专门写一个类的实例)
// 如果这个变量放在初始化块的后面,是会报错的,因为你根本没有被初始化
public String p_Field = "父类--变量";
int a = getParent();
// 静态初始化块
static {
System.out.println(p_StaticField);
System.out.println("父类--静态初始化块");
}
// 初始化块
{
System.out.println(p_Field);
System.out.println("父类--初始化块");
}
{
System.out.println(a);
}
// 构造器
public Parent() {
this(100);
System.out.println("父类--构造器");
}
public Parent(int i) {
System.out.println("父类带参构造器" + "******" + i);
}
private int getParent() {
System.out.println("********getParent()*********");
return 6;
}
}
class SubClass extends Parent {
// 静态变量
public static String s_StaticField = "子类--静态变量";
// 变量
public String s_Field = "子类--变量";
// 静态初始化块
static {
System.out.println(s_StaticField);
System.out.println("子类--静态初始化块");
}
// 初始化块
{
System.out.println(s_Field);
System.out.println("子类--初始化块");
}
// 构造器
public SubClass() {
this(200);
//super(300);
System.out.println("子类--构造器");
}
public SubClass(int i) {
//super(400);
System.out.println("子类带参构造器" + "*******" + i);
}
}
public class Super_Sub_Contr{
// 程序入口
public static void main(String[] args) {
System.out.println("*************in main***************");
new SubClass();
System.out.println("*************second subClass***************");
new SubClass();
}
}
这里子类和父类都有一个无参构造函数和带参构造函数,下面分以下几种情况讨论一下:
1、初始化时,父类的无参构造函数调用this(100), 子类的无参函数调用this(200),此种情况下,子类和父类的无参构造函数和带参构造函数都会初始化;
2、父类不修改,此时将子类的带参构造函数的super(400)注释去掉,你会发现此种情况下,父类的无参构造函数没有调用,带参构造函数还是调用的;
3、父类不修改,将子类的无参构造函数的this(200)注释,改为super(300),此种情况下,子类的带参构造函数和父类的无参构造函数都没有调用;
上面部分想法借鉴了:http://blog.csdn.net/mad1989/article/details/20793539
最后,再看看下面代码的执行结果:
public class Test {
Person person = new Person("Test");
static{
System.out.println("test static");
}
public Test() {
System.out.println("test constructor");
}
public static void main(String[] args) {
new MyClass();
}
}
class Person{
static{
System.out.println("person static");
}
public Person(String str) {
System.out.println("person "+str);
}
}
class MyClass extends Test {
Person person = new Person("MyClass");
static{
System.out.println("myclass static");
}
public MyClass() {
System.out.println("myclass constructor");
}
}
test static
myclass static
person static
person Test
test constructor
person MyClass
myclass constructor