`
luhantu
  • 浏览: 200313 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

父类子类变量,块,构造函数加载先后顺序

    博客分类:
  • Java
阅读更多

1. 如果B继承A,在new B()时候,java代码的执行顺序:

 

JVM装载

初始化父类的静态成员变量

初始化父类的静态代码块

初始化子类的静态成员变量

初始化子类的静态代码块

初始化父类的非静态成员变量

初始化父类的非静态代码块

调用父类的默认构造方法

初始化子类的非静态成员变量

初始化子类的非静态代码块

调用子类的构造方法

测试代码:

package com;

public class TestHello {

	static class A {
		public int a1 = 21;
	    static int a = 2;
	    {
	         System.out.println("父类的非静态代码块正在运行,非静态变量a1的值为=" + a1 + " 静态变量的a的值为=" + a);
	    }
	    static {
	         System.out.println("父类的静态代码块正在运行,静态变量的a的值为=" + a);
	    }
	    public A() {
	         System.out.println(a1 + "父类构造函数正在运行,非静态变量a1的值为=" + a1 + " 静态变量的a的值为=" + a);
	    }
	}
	
	static class B extends A {
		public int a1 = 31;
	    static int a = 3;
	    
	    {
	    	 System.out.println("子类的非静态代码块正在运行,非静态变量a1的值为=" + a1 + " 静态变量的a的值为=" + a);
	    }
	    static {
	    	System.out.println("子类的静态代码块正在运行,静态变量的a的值为=" + a);
	    }
	    public B() {
	    	 System.out.println(a1 + "子类构造函数正在运行,非静态变量a1的值为=" + a1 + " 静态变量的a的值为=" + a);
	    }
	}
	
	public static void main(String[] args) {
		B b = new B();
    }
}

 执行结果为:

父类的静态代码块正在运行,静态变量的a的值为=2
子类的静态代码块正在运行,静态变量的a的值为=3
父类的非静态代码块正在运行,非静态变量a1的值为=21 静态变量的a的值为=2
21父类构造函数正在运行,非静态变量a1的值为=21 静态变量的a的值为=2
子类的非静态代码块正在运行,非静态变量a1的值为=31 静态变量的a的值为=3
31子类构造函数正在运行,非静态变量a1的值为=31 静态变量的a的值为=3

 2)若果想要显式调用父类的构造方法则可以使用super(),来调用,但是super关键字必须放在构造放的第一行,而且只能放在第一行,不然编译不通过。

3)this 指针指向的是当前的实例

 

package com.base;
class Base {
	private int i = 2 ;
	public Base(){
		this.display() ;
	}
	public void display(){
		System.out.println(i);
	}
}

class Derived extends Base {
	private int i = 22 ;
	public Derived(){
		i = 222 ;
	}
	public void display(){
		System.out.println(i);
	}
}

public class Test {
	public static void main(String[] args) {
		new Derived() ;
	}
}
 输出结果为:0

 

怎么会是0 呢?

当我们调用new Derived() ;创建Derived实例的时候,系统会为Derived对象分配内存空间,Derived会有两个i实例变量,会分配两个空间来保存i的值。分配完空间以后i的值为0,如果有引用类型则引用类型的值为null。

接下来程序在执行Derived的构造器之前会执行Base的构造器,表面上看Base的构造器中只有一行代码,但是在父类中定义i的时候执行的初始值2,因此经过编译之后,该构造方法中应该包含如下两行代码:

i =2 ;

this.display() ;

程序先将Base中的i赋值为2,然后执行display方法。此处有一个关键字this,this到底代表谁呢?表面上看this代表的是Base的当前实例,但是实际上代码是放在Derived的构造器中的,所以this最终代表的是Derived的当前实例(编译类型是Base而实际引用一个Derived对象),所以如果在父类的构造方法中直接输出System.out.println(this.i) ;则输出的结果为2。但是调用this.display()方法,此时调用的是

子类中重写的display方法,输出的变量i也是子类中的i,但是此时子类中的变量i还没有赋值,所以输出结果为0。

为了详细的看清楚this变量到底代表什么实例,我们将Base的构造方法修改如下:

public Base(){

System.out.println(this.i);

System.out.println(this.getClass());

this.display() ;

}

再次运行程序,结果为:

2

class edu.qichao.chapter2.Derived

0

可以看到this代表的是Derived的实例,但是编译的时候类型为Base,所以输出this.i的值为2。

4)继承成员变量和成员方法的区别

package com.base;
class Animal {
	private String desc ;
	public Animal(){
		this.desc = getDesc() ;
	}
	 
	public String getDesc(){
		return "Animal" ;
	}
	public String toString(){
		return desc ;
	}
	
}
public class Wolf extends Animal {
	private String name ;
	private double weight ;
	public Wolf(String name , double weight){
		this.name = name ;
		this.weight = weight ;
	}
	
	public String getDesc(){
		return "Wolf[name=" + name + ",weight=" + weight + "]" ;
	}
	
	 
	
	public static void main(String[] args){
		System.out.println(new Wolf("灰太狼" , 3));
	}
}

程序运行结果为:

2

2

-----------------

20

20

-----------------

2

20

-----------------

2

在上面的程序中,不管是d变量、还是bd变量、还是都d2b变量。只要他们指向一个Derived对象,则不管他们声明时用了什么类型,当通过这些变量调用方法时,方法的行为总是表现出他们的实际类型的行为,但是如果通过这些变量来访问他们所指向对象的实例变量的时候,这些实例变量的值总是表现出声明这些变量所用类型的行为。

由此可见,java处理成员变量和成员方法的继承时是有区别的。

参考:http://www.2cto.com/kf/201110/109053.html

分享到:
评论

相关推荐

    MFC的程序框架剖析

    在构造子类对象时,会自动调用父类的构造函数,此时在父类的构造函数中的this指针所指向的是子类对象地址 10、AfxWinMain函数 MFC程序的WinMain函数是通过调用AfxWinMain函数来完成它的功能的 注:Afx前缀的函数代表...

    java面试800题

    (3) super.([paramlist]) //调用父类中的构造函数 在类方法中(static),不能使用this或super修饰符 " Q0045 Java中是怎样捕获异常的? "try { //statement01 } catch(Exception e) { //statement02 } finally { ...

    疯狂JAVA讲义

    5.9.2 初始化块和构造器 161 5.9.3 静态初始化块 162 5.10 本章小结 165 本章练习 165 第6章 面向对象(下) 166 6.1 基本数据类型的包装类 167 6.2 处理对象 170 6.2.1 打印对象和toString方法 170 6.2.2 =...

    python cookbook(第3版)

    7.7 匿名函数捕获变量值 7.8 减少可调用对象的参数个数 7.9 将单方法的类转换为函数 7.10 带额外状态信息的回调函数 7.11 内联回调函数 7.12 访问闭包中定义的变量 第八章:类与对象 8.1 改变对象的字符串...

    Java开发技术大全 电子版

    4.5.2使用super调用父类的构造方法157 4.6继承的内部处理158 4.7多态的基本概念159 4.8重载159 4.8.1普通方法的重载160 4.8.2构造方法的重载161 4.8.3重载的解析163 4.8.4重载与覆盖的区别165 4.9运行时多态...

    java 面试题 总结

    不能有抽象构造函数或抽象静态方法。Abstract 类的子类为它们父类中的所有抽象方法提供实现,否则它们也是抽象类为。取而代之,在子类中实现该方法。知道其行为的其它类可以在类中实现这些方法。 接口(interface)...

    python入门到高级全栈工程师培训 第3期 附课件代码

    11 在子类中调用父类方法 12 super调用父类的方法 13 选择系统作业讲解 第26章 01 学生自主复习 02 分享列表 03 多态 04 封装 05 面向对象概念总结 06 反射 07 反射及动态导入模块 08 类的内置attr属性 09 类内置...

    超级有影响力霸气的Java面试题大全文档

    不能有抽象构造函数或抽象静态方法。Abstract 类的子类为它们父类中的所有抽象方法提供实现,否则它们也是抽象类为。取而代之,在子类中实现该方法。知道其行为的其它类可以在类中实现这些方法。  接口(interface...

    最新Java面试宝典pdf版

    70、TreeSet里面放对象,如果同时放入了父类和子类的实例对象,那比较时使用的是父类的compareTo方法,还是使用的子类的compareTo方法,还是抛异常! 48 71、说出一些常用的类,包,接口,请各举5个 49 72、java中有...

    Java面试笔试资料大全

    70、TreeSet里面放对象,如果同时放入了父类和子类的实例对象,那比较时使用的是父类的compareTo方法,还是使用的子类的compareTo方法,还是抛异常! 48 71、说出一些常用的类,包,接口,请各举5个 49 72、java中有...

    Java面试宝典2010版

    70、TreeSet里面放对象,如果同时放入了父类和子类的实例对象,那比较时使用的是父类的compareTo方法,还是使用的子类的compareTo方法,还是抛异常! 71、说出一些常用的类,包,接口,请各举5个 72、java中有几种...

    Java面试宝典-经典

    70、TreeSet里面放对象,如果同时放入了父类和子类的实例对象,那比较时使用的是父类的compareTo方法,还是使用的子类的compareTo方法,还是抛异常! 48 71、说出一些常用的类,包,接口,请各举5个 49 72、java中有...

    JAVA面试宝典2010

    70、TreeSet里面放对象,如果同时放入了父类和子类的实例对象,那比较时使用的是父类的compareTo方法,还是使用的子类的compareTo方法,还是抛异常! 48 71、说出一些常用的类,包,接口,请各举5个 49 72、java中有...

    java面试题大全(2012版)

    70、TreeSet里面放对象,如果同时放入了父类和子类的实例对象,那比较时使用的是父类的compareTo方法,还是使用的子类的compareTo方法,还是抛异常! 48 71、说出一些常用的类,包,接口,请各举5个 49 72、java中有...

    java面试宝典2012

    70、TreeSet里面放对象,如果同时放入了父类和子类的实例对象,那比较时使用的是父类的compareTo方法,还是使用的子类的compareTo方法,还是抛异常! 52 71、说出一些常用的类,包,接口,请各举5个 54 72、java中有...

    Java面试宝典2012版

    70、TreeSet里面放对象,如果同时放入了父类和子类的实例对象,那比较时使用的是父类的compareTo方法,还是使用的子类的compareTo方法,还是抛异常! 48 71、说出一些常用的类,包,接口,请各举5个 49 72、java中...

    Java面试宝典2012新版

    70、TreeSet里面放对象,如果同时放入了父类和子类的实例对象,那比较时使用的是父类的compareTo方法,还是使用的子类的compareTo方法,还是抛异常! 48 71、说出一些常用的类,包,接口,请各举5个 49 72、java中有...

Global site tag (gtag.js) - Google Analytics