A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 黄玉昆 黑马帝   /  2013-2-5 10:26  /  3880 人查看  /  13 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 黄玉昆 于 2013-2-5 19:31 编辑

在毕老师的视频讲解中,说道关于抽象类在创建对象上的问题:抽象类不可用new创建对象,因为调用抽象方法没有意义(抽象方法为类中成员)。看下面一段代码:
  1. <font size="1">/*
  2. 问题:关于抽象类不能创建对象,但能创建数组的测试
  3. */

  4. //抽象类Person
  5. abstract class Person
  6. {
  7.    private String name;
  8.    public Person(String name)
  9.    {
  10.       this.name = name;
  11.    }
  12.    //抽象方法:对人的描述,但对每种人的描述是不清楚的,所以用抽象方法
  13.    public abstract String getDescription();

  14.    public String getName()
  15.    {
  16.       return name;
  17.    }
  18. }</font>
  19. <font size="1">
  20. //Student继承父类Person
  21. class Student extends Person
  22. {
  23.    public Student(String name)
  24.    {
  25.       super(name);
  26.    }
  27.    //复写超类的抽象方法,对学生进行具体描述
  28.    public String getDescription()
  29.    {
  30.       return "I'm a student.";
  31.    }
  32. }
  33. //Worker继承父类Person
  34. class Worker extends Person
  35. {
  36.    public Worker(String name)
  37.    {
  38.       super(name);
  39.    }
  40.    //复写超类的抽象方法,对工人进行具体描述
  41.    public String getDescription()
  42.    {
  43.       return "I'm a worker.";
  44.    }
  45. }
  46. //测试
  47. class PersonText
  48. {
  49.    public static void main(String[] args)
  50.    {
  51.       Person[] p = new Person[2];//用抽象类创建数组
  52.       //再创建两个对象
  53.       p[0] = new Student("Sun");
  54.       p[1] = new Worker("Wu");
  55.       System.out.println(p[0].getName() + ":" + p[0].getDescription());
  56.       System.out.println(p[1].getName() + ":" + p[1].getDescription());
  57.    }
  58. }</font>
复制代码
数组也是对象,只不过有些特殊而已,既然有new存在,就说明在内存中创建了对象,为其开辟了一片空间,但是抽象类不能实例化。那么new出来的Person数组放在哪了呢?内存中又是怎么分配的呢?
是不是说抽象类不可以创建对象,但是又可以创建数组,就有些矛盾呢?
求解答,最好有图并分好步骤的解释,谢谢。

点评

问题解决后 请注意从新编辑帖子,更改为已解决  发表于 2013-2-5 16:12

评分

参与人数 1技术分 +1 收起 理由
Rancho_Gump + 1 赞一个!

查看全部评分

13 个回复

正序浏览
陈科宇 发表于 2013-2-5 15:31
对,针对你这个,我刚才还特意写了一篇关于数组的日志。我再讲个例子,你或许就更明白了。int是基本类型 ...

基本上理解了,十分感谢你的帮助
回复 使用道具 举报
对于这个问题,我看了这两位朋友的热心帮助,我基本有些清晰了,我把自己的理解在这里整理一下:
在这里,Person[] p = new Person[2]只是创建了两个数组类型的元素,并不是Person类对象,在这里只是一种引用。而下面的new Student和new Worker才真正创建了两个对象,分别赋值给数组中的两个元素,或者说是两个变量。
再次感谢两位朋友。

点评

实例化一个类的对象和创建数组是两个概念。  发表于 2013-2-5 16:10

评分

参与人数 1技术分 +1 收起 理由
舒远 + 1 总结的很好。理解了更好。

查看全部评分

回复 使用道具 举报
黄玉昆 发表于 2013-2-5 15:28
我不是急躁,只是不明白他们之间的赋值过程。你说的给它规定了类型,我差不多有些明白了。谢谢你的解答 ...

对,针对你这个,我刚才还特意写了一篇关于数组的日志。我再讲个例子,你或许就更明白了。int是基本类型对吧。但是int[]却是引用类型。你不能说 int[] a=new int[2]是创建了两个基本类型的变量吧,这是不是矛盾了呢。其实没有矛盾,是认识误区。

评分

参与人数 2技术分 +1 黑马币 +1 收起 理由
舒远 + 1 赞一个!
黄玉昆 + 1 很给力!

查看全部评分

回复 使用道具 举报
吴在强 发表于 2013-2-5 15:12
这个是图像,刚刚那个图像没显示!自己慢慢体会!

谢谢你的图解
回复 使用道具 举报
陈科宇 发表于 2013-2-5 15:24
你应该仔细看我给你的回复。不要急躁。我已经说过了,Person[] p=new  Person[2]是在堆内存中创建了两个 ...

我不是急躁,只是不明白他们之间的赋值过程。你说的给它规定了类型,我差不多有些明白了。谢谢你的解答
回复 使用道具 举报
黄玉昆 发表于 2013-2-5 15:18
虽然是null,但是还是赋值了啊,只不过是空而已,是对对象更确切地说是数组,初始化了而已。既然可以Pers ...

不要把Person p=new Person[2]理解为创建两个Person对象。这是你认识上的误区。
回复 使用道具 举报
吴在强 发表于 2013-2-5 15:11
你认真看看你代码,你自己创建的代码如下:
//问题:关于抽象类不能创建对象,但能创建数组的测试

怎么又涉及到了多态了呢(多态还没学到)?你说的”实现类的对象“是什么意思啊?你说的这个“是数组对象而不是Person对象啊 ,这个数组只能保存Person类型的对象!”数组中存放的不是对象的值吗?你说Person类型不能创建对象,哪里来Person类型的对象啊?还有,你传的图片,我看不到啊。
回复 使用道具 举报
黄玉昆 发表于 2013-2-5 15:18
虽然是null,但是还是赋值了啊,只不过是空而已,是对对象更确切地说是数组,初始化了而已。既然可以Pers ...

你应该仔细看我给你的回复。不要急躁。我已经说过了,Person[] p=new  Person[2]是在堆内存中创建了两个数组元素,而不是Person对象。只是给它规定了类型,它只能存放或指向Person对象。
回复 使用道具 举报
陈科宇 发表于 2013-2-5 12:09
朋友,你的Person[] p = new Person[2],只是确定了数组的类型为Person,长度为2,而此时并没有Per ...

虽然是null,但是还是赋值了啊,只不过是空而已,是对对象更确切地说是数组,初始化了而已。既然可以Person[] p = new Person[2]这样写,就说明在堆内存中是存在的,我目前知道的是,堆内存中只有对象,那么这个所谓的不能创建对象,到底是怎么回事,我只是不太明白在堆内存中的分配情况。
回复 使用道具 举报
这个是图像,刚刚那个图像没显示!自己慢慢体会!

tuxian.PNG (14.26 KB, 下载次数: 149)

tuxian.PNG

评分

参与人数 2技术分 +1 黑马币 +1 收起 理由
Rancho_Gump + 1 赞一个!
黄玉昆 + 1 赞一个!

查看全部评分

回复 使用道具 举报
你认真看看你代码,你自己创建的代码如下:
//问题:关于抽象类不能创建对象,但能创建数组的测试


//抽象类Person
abstract class Person
{
   private String name;
   public Person(String name)
   {
      this.name = name;
   }
   //抽象方法:对人的描述,但对每种人的描述是不清楚的,所以用抽象方法
   public abstract String getDescription();

   public String getName()
   {
      return name;
   }
}

//Student继承父类Person
class Student extends Person
{
   public Student(String name)
   {
      super(name);
   }
   //复写超类的抽象方法,对学生进行具体描述
   public String getDescription()
   {
      return "I'm a student.";
   }
}
//Worker继承父类Person
class Worker extends Person
{
   public Worker(String name)
   {
      super(name);
   }
   //复写超类的抽象方法,对工人进行具体描述
   public String getDescription()
   {
      return "I'm a worker.";
   }
}
//测试
public class PersonText
{
   public static void main(String[] args)
   {
      Person[] p = new Person[2];//用抽象类创建数组
      //再创建两个对象
      p[0] = new Student("Sun");
      p[1] = new Worker("Wu");
      System.out.println(p[0].getName() + ":" + p[0].getDescription());
      System.out.println(p[1].getName() + ":" + p[1].getDescription());
   }
}


Person[] p = new Person[2];这个创建出来的就是数组对象,而不是Person对象。
下面两个是java的多态,父类指向子类对象
p[0] = new Student("Sun");
p[1] = new Worker("Wu");
所有过程都没有直接创建抽象类的对象啊,p[0] = new Student("Sun");p[0]指向的是实现类的对象
抽象类是创建不了对象滴
但是可以有实现类的对象
创建的地址指向过程是 这样的:
C:\\tuxian.PNG

换句话说,是数组对象而不是Person对象啊 ,这个数组只能保存Person类型的对象!应该能明白了吧!
回复 使用道具 举报
        朋友,你的Person[] p = new Person[2],只是确定了数组的类型为Person,长度为2,而此时并没有Person对象产生。只有当你赋值给p[0],p[1]时数组的两个元素才不为null。希望我的解答对你有帮助。
回复 使用道具 举报
      朋友,你这里有个误解。以为Person[] p = new Person[2]创建了两个person对象。看了下面的代码就明白了。
      public class PersonTest
{
public static void main(String[] args)
{
    Person[] p = new Person[2];//用抽象类创建数组
    System.out.println("p[0]==null:"+(p[0]==null));
    System.out.println("p[1]==null:"+(p[1]==null));

    //再创建两个对象
    p[0] = new Student("Sun");
    p[1] = new Worker("Wu");
    System.out.println(p[0].getName() + ":" + p[0].getDescription());
    System.out.println(p[1].getName() + ":" + p[1].getDescription());
    /*
     * p[0]==null:true
     * p[1]==null:true
     *Sun:I'm a student.
     *Wu:I'm a worker.
     *
     */
}
}
      

评分

参与人数 1技术分 +1 收起 理由
Rancho_Gump + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马