父类对象引用指向子类对象引用

tt_lin 发布于 2013/07/07 10:10
阅读 1K+
收藏 0

开源之夏第三届火热来袭,高校学生参与赢万元奖金!>>>

     最近学的java对父类引用指向子类对象不是很了解他们在内存中的机制。如果父类对象和子类对象有相同名字的一个属性。

     和下面中的一样,A bNext = new B();在栈空间生成了一个A的引用b,指向堆空间中new出来的B对象。如果不同的引用,得到的结果会不一样。希望大神能讲下为什么指向的是一个相同的对像为什么父类引用会使用被隐藏的父类属性,子类引用会使用子类的属性


public class A
{
	int a=100;
	public static void main(String[] args)
	{
		B bFirst = new B();
		A bNext = new B();
		System.out.println(bFirst.a+"   "+bNext.a);
	}
}
class B extends A{
	int a = 0;
}


加载中
0
Erroooooor
Erroooooor

这个如果通看main方法所生成的字节码就很清楚了

L0
    LINENUMBER 6 L0
    NEW B
    DUP
    INVOKESPECIAL B.<init>()V
    ASTORE 1
   L1
    LINENUMBER 7 L1
    NEW B
    DUP
    INVOKESPECIAL B.<init>()V
    ASTORE 2
   L2
    LINENUMBER 8 L2
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    NEW java/lang/StringBuilder
    DUP
    ALOAD 1
    GETFIELD B.a : I
    INVOKESTATIC java/lang/String.valueOf(I)Ljava/lang/String;
    INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V
    LDC "   "
    INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    ALOAD 2
    GETFIELD A.a : I
    INVOKEVIRTUAL java/lang/StringBuilder.append(I)Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;
    INVOKEVIRTUAL java/io/PrintStream.println(Ljava/lang/String;)V
上面就是main方法对应的字节码内容,
GETFIELD A.a
这个指令就是拿对象的属性,实际上当把源程序编译成class的时候,java编译器就已经告诉了程序使用哪个类的属性.

Erroooooor
Erroooooor
回复 @tt_lin : javap出来的是最原始的,很多都是以"#数字"的形式显示的,这表示常量池入口,所有类名,基本类型的一些数据,string类型的都会放到这个常量池里面,想深入了解这个可以看看Class的格式,我用的是asm的一个eclipse插件看的,这个插件就显示的比较直观,而且当你鼠标定位到代码的某一行的时候,字节码也会同步定位到对应到。
tt_lin
tt_lin
这个字节码为什么和我javap出来的不一样额,看的不是很懂,能讲下关系么?
0
狮子暴走
狮子暴走
其实 我理解的是   A bNext = new  B(); 这个类似于 对象的强制类型转化了  
tt_lin
tt_lin
嗯,我晓得会是那种结果,可是搞不明白内存里面是怎么变化的
0
zhoulc
zhoulc
 总的来说对于一个引用变量而言,当通过该变量访问它所引用的对象的实例变量时,该实例变量的值取决于声明该变量时类型,当通过该变量访问它所引用的对象的方法时,该方法行为取决于它所实际引用的对象的类型。
tt_lin
tt_lin
好像绕口令呀~,不过我明白你的意思啦。属性是引用指向的属性,方法是实例指向的方法
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部
返回顶部
顶部