黑马程序员技术交流社区

标题: 多态 [打印本页]

作者: 黄昆    时间: 2012-7-13 09:51
标题: 多态
第一题:
class A{
int num=2;
}
public class B extends A{
int num=3;
public static void main(String[] args) {
  A a=new B();
  System.out.println(a.num );
}
}
运行结果是:2
第二题:
class Super
{
  int i=0;
  public Super(String a)
  {
   System.out.println("A");
   i=1;
  }
  public Super()
  {
   System.out.println("B");
   i+=2;
  }
}
class Demo extends Super
{
  public Demo(String a)
  {
   System.out.println("C");
   i=5;   
  }
  public static void main(String[] args)
  {
   int i=4;
   Super d=new Demo("A");
   System.out.println(d.i);
  }
}
运行结果是:B C 5  
问题:为什么第二题的运行结果不是:B C 0 呢?在多态中成员变量的特点:无论编译还是运行都是参考引用型变量所属的类。
这两道题是不是矛盾呀?有点不理解。求解!

作者: 陆强强    时间: 2012-7-13 10:01
  Super d=new Demo("A");先public Demo(String a)初始化,因为super()隐式语句的存在,调用父类的 public Super()打印“b”,再给I赋值2
然后再打印“C”,最后给I赋值5,
System.out.println(d.i);这里的I继承了super后的I,不是主函数的I

作者: 黄昆    时间: 2012-7-13 10:10
陆强强 发表于 2012-7-13 10:01
Super d=new Demo("A");先public Demo(String a)初始化,因为super()隐式语句的存在,调用父类的 publi ...

public Super()
   {
    System.out.println("B");
    i+=2;
   }
调用父类的构造函数,此时的i是代表父类中的,还是子类中的?
作者: 陆强强    时间: 2012-7-13 10:19
hkylp 发表于 2012-7-13 10:10
public Super()
   {
    System.out.println("B");

父类,只不过这里new Demo("A");父类指向了子类的引用,所以构造函数
从子类开始算起,再调用父类,最后回到子类;
但d永远看的是他所在的类,也就是Super d=new Demo("A");
中的Super,d.i也就是指向Super中的I。
作者: 封明川    时间: 2012-7-13 10:27
本帖最后由 封明川 于 2012-7-13 10:31 编辑

class Super
{
  int i=0;
  public Super(String a)
  {
   System.out.println("A");
   i=1;
  }
  public Super()
  {
   System.out.println("B");
   i+=2;  
  }
}
class Demo extends Super
{
  public Demo(String a)  //2、父类初始化完,就开始调用子类的构造函数,因为没有定义i ,所以引用了父类的变量 i
  {
   System.out.println("C");
   i=5;   //3、给这个变量重新定义了一个值,
  }
  public static void main(String[] args)
  {
   int i=4;
   Super d=new Demo("A");  //1、这里对象实例化的时候先是隐式的一个super();调用父类的构造函数。
   System.out.println(d.i);  //4、这里实际上是子类的变量引用复写了父类的变量,所以结果是5
  }
}

作者: 黄丽慧    时间: 2012-7-13 10:28
楼主这两个题目,并不互相矛盾的,跟语句先后的执行顺序有关系,很细微的差别就会引起结果的差异
class A{
int num=2;
}
public class B extends A{
int num=3;//你这里的num定义在实例化之前
public static void main(String[] args) {
  A a=new B();//这里一创建实例,调用隐式的super(),前面的那个num就被重新赋值成2了,所以下面打印出来的结果是2
  System.out.println(a.num );
}
}
class Super
{
  int i=0;
  public Super(String a)
  {
   System.out.println("A");
   i=1;
  }
  public Super()
  {
   System.out.println("B");
   i+=2;
  }
}
class Demo extends Super
{
  public Demo(String a)
  {
   System.out.println("C");
   i=5;   
  }
  public static void main(String[] args)
  {
   int i=4;
   Super d=new Demo("A");//这里一创建实例,调用public Demo(String a)这个构造方法,先执行super(),所以打印B,i=2,紧接着打印C,又对i进行赋值,i=5.因此d.i的结果就是5了
   System.out.println(d.i);
  }
}
作者: 黄昆    时间: 2012-7-13 10:34
明白了
作者: 陆鹏    时间: 2012-7-13 10:42
本帖最后由 陆鹏 于 2012-7-13 10:44 编辑

楼主请认真看程序执行顺序和红字部分。

package cn.heima;
class Super
{
  int i=0;
  public Super(String a)
  {
   System.out.println("A");
   i=1;
  }
  public Super()//5---->跳到6
  {
   System.out.println("B");//6---->打印"B"
   i+=2;//7.此时i=2了
  }
}
class Demo extends Super
{
  public Demo(String a)//3---->跳到4
  {
   //默认有一个super();4----->跳到5.
   System.out.println("C");//9--->打印C
   i=5;//10---->将5赋给i
  }
  public static void main(String[] args)
  {
   int i=4;//1---->这个i是在栈内存中,而后面的i是堆内存中的,所以这个i没有被用
   Super d=new Demo("A");//2----->跳到序号3
   System.out.println(d.i);//8--->跳到9
          //11---->将堆内存中的i打印出来,此时i已经变为5了。
  }
}

作者: 黄昆    时间: 2012-7-13 12:14
黄丽慧 发表于 2012-7-13 10:28
楼主这两个题目,并不互相矛盾的,跟语句先后的执行顺序有关系,很细微的差别就会引起结果的差异:
class A ...

恩,同感呀,感觉分数好难得呀!
作者: 文密    时间: 2012-7-13 17:42
class A{
int num=2;
}
public class B extends A{
int num=3;
public static void main(String[] args) {
  A a=new B();
  System.out.println(a.num );
}
}
其实第一题很好理解:
记住这句话就行了
在多态中成员变量有特点:
无论编译和运行,都参考左边(引用型变量所属的类)。

第二题:
class Super
{
  int i=0;
  public Super(String a)
  {
   System.out.println("A");
   i=1;
  }
  public Super()
  {
   System.out.println("B"); //4:打印"B"  
i+=2;          //5:  i赋值为2;
  }
}
class Demo extends Super
{
  public Demo(String a)
  {
     //3  通过//super();隐示 调用父类有空构造函数
System.out.println("C");  //6 :打印出“c”
   i=5;    //7把I赋值为5
  }
  public static void main(String[] args)
  {
   int i=4;    //1此变量在栈内存里面,没有在堆内存   
Super d=new Demo("A");//2父类的引用指向了自己的子类对象   System.out.println(d.i);  所以//d.i=5
  }
所以最后显示的是BC5;





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2