黑马程序员技术交流社区

标题: 关于多态的迷惑 [打印本页]

作者: 孙传磊    时间: 2013-3-3 17:34
标题: 关于多态的迷惑
本帖最后由 孙传磊 于 2013-3-8 11:40 编辑

class Fu {
boolean show(char a){
          System.out.print(a);
          return true;
  }
}
class Demo  extends Fu {
        
         public static void main (String[] args){
                 int i=0;
                 Fu f=new Demo();
                Demo d=new Demo();
                for(f.show('A');f.show('B')&&(i<2);f.show('C')){
                        i++;
                        d.show('D');
                }}
         
                 boolean show(char a){
                          System.out.print(a);
                          return false;
                  
         }
}
输出的结果是:AB,情况(二)而当我在 Fu类和子类的  boolean show(char a){…} 方法前都加上static 输出结果就变成:ABDCBDCB 这是为什么?情况(三)是在 父类中定义一个成员变量 int num=8 ;在其子类中也定义一个成员变量int num = 5;在通过 Fu f=new Demo();声明对象,并通过System.out.print(f.num);输出结果为什么是 父类的 8 呢?这三种情况在内存中开辟空间的情况是什么样的?
作者: 折纸时代    时间: 2013-3-3 17:59
首先 两个show方法都是实例方法时,  
子类的show方法是重写了父类的..  
而且返回值还是false, 意味着for循环条件不满足,没有循环. 只是打印了前面两个char.
而全部用static修饰的时候, 就是调用了父类的静态方法.. 子类没有重写父类方法.


其次, 多态中的成员变量是看编译时期的,和运行时期无关.
所以,编译时期是父类调用成员变量, 输出依然是父类的成员变量.

其实这些问题不用太纠结,多看看视频就明白了.
作者: 王智威    时间: 2013-3-3 18:55
第一种情况就是简单的覆盖,没什么特别的,你应该知道了吧。

而第二种和第三种情况是一样的,你知道静态方法是可以不用new对象的,之所以说以它可以直接用是因为类在加载的时候静态的东西都已经进内存了。

所以 Fu f=new Demo();它是父类的对象,所以里面的静态方法和静态成员变量就是父类的。
你如果要用子类的静态方法和成员你要Demo d=new Demo();
静态的看等号左边的就可以了


作者: 谢洋    时间: 2013-3-3 23:25
本帖最后由 谢洋 于 2013-3-3 23:51 编辑

一、
1、当发生Fu f=new Demo();同时在堆内存中生成一个子类对象和一个父类的对象;而这个父类的对象是存在于这个子类对象中的,
也就是说父类型的引用: f 是指向子对象中的父对象;
2,对象在堆内存中是怎么存放的?
其实对象在堆内存放的只有非静态成员变量,而没有对象的方法;因为方法每必要每个对象都有一份,下面有解
3,那么方法在那里?其实类加载被加载时,是被加载到内存的方法区中;把静态的东西放到存内的静态区,而非静态的放到内存的非静态区;
当产生对象时,jvm就是通过这些内存区的字节码生成对象,并把它存放到位堆中;
当对象要调用非静态方法时,jvm会通过方法区中的非静态函数在栈内存中创建一个方法,且该方法指向调用它的对象(传说中的this);
对于静态的方法被调用,就不多说了;
二、现在可以对打印结果分析了:
1、第一种情况:因为 Fu f=new Demo();创建的是子类对象,且每个子类对象在调用非静态方法时都会在栈中产生一个指向本对象的方法,
所以第一种情况执行的是子类的方法。
2、第二种情况:因为f 是父类的引用,且把它指向了子类对象,也就是说f指向了子对象中的父对象,因为这时执行的是static方法,
与对象无关,所以执行的是父的static方法
3、第三种情况,f 是指向子对象里面的f对象,所以得到是父类对象的成员;那么怎么获取子的num?
可通过在子类中添加getNum(){return this.num}方法,通过f.getNum就行了




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