【问题标题】:create an object of an abstract class != instantiate the abstract class?创建一个抽象类的对象!=实例化抽象类?
【发布时间】:2012-01-27 15:57:22
【问题描述】:

我了解到我们不能实例化抽象类。但是今天我测试了一些代码,我对此感到困惑。

package MainPackage;

abstract class abstractClass {
    abstract abstractClass a_function();
}

public class Src {
    abstractClass m;
    public abstractClass abstractClassTest() {
        return m.a_function();
    }
    public static void main(String args[]) {
        System.out.println("Hello world!");
    }
}

这里我创建了一个抽象类 abstractClass 并在 abstractClassTest() 函数中返回它。并且编译成功,没有错误! IMO 在返回某些东西之前,计算机应该创建一个该类型的对象。在这里它应该在 return m.function() 之前创建一个 abstractClass 的对象,我无法理解。我认为我们不能实例化一个抽象类意味着我们不能创建一个抽象类的对象或者我们不能新建一个类(例如abstractClass m = new abstractClass() is illegal。但是从上面的代码看来,我们可以创建一个抽象类的对象。怎么可能实现?对于代码abstractClass m,计算机看到代码会做什么?不能说java已经为代码abstractClass m实例化了抽象类m吗?如果java不实例化类abstractClass,它如何在代码abstract abstractClass a_function();中返回abstractClass的对象?

【问题讨论】:

  • 你不是 instantiating 一个抽象类,只是使用它的引用。
  • 请注意,您的代码没有实例化任何抽象类对象。如果要创建 abstractclass 的子类,则可以实例化它 (abstractClass m = new childClass(...)),然后 m.a_function 将是有效的。
  • 正如您所指出的,您不能“新建”抽象类。您的代码中的任何地方都没有 new - 那么问题出在哪里?
  • Bhushan 和 Sam DeHaan,既然您是在回答这个问题,那么您应该将其作为答案,而不是作为评论。

标签: java abstract instantiation


【解决方案1】:

是的,它应该编译没有错误。但是,如果您曾经调用过abstractClassTest,它会在执行时抛出NullPointerException,因为您从未初始化m 变量以引用实际实例。为此,您必须创建一个 concrete 类来继承您的抽象类。

例如:

public class ConcreteClass extends AbstractClass {
    @Override AbstractClass a_function() {
       return this;
    }
}

public class Src {
    private AbstractClass m = new ConcreteClass();

    public AbstractClass abstractClassTest() {
        return m.a_function();
    }
    public static void main(String args[]) {
        new Src().abstractClassTest();
    }
}

请注意,您的代码中没有任何内容会创建抽象类的实例。仅仅因为您拥有该类型的变量并不意味着已创建该类型的 object

【讨论】:

  • 如果你尝试直接用抽象类的实例初始化变量,你会得到一个编译错误。
  • 只是为了完整性而标记。 :-)
【解决方案2】:

m 永远不会被分配,并且您永远不会尝试使用 new 关键字实例化一个新的 abstractClass。如果您的代码实际上到达了 abstractClassTest,您只会得到一个空指针异常。我认为你可能混淆了声明一个变量并实际给它一个值。

【讨论】:

    【解决方案3】:

    您不能直接实例化抽象类,而且您的代码实际上并没有这样做。您所拥有的只是对抽象类的某个子类或其他子类的引用,当您实例化“m”时,您必须提供一个实际的具体子类。

    你会得到一个与接口类似的模式。这样写是很合法的,例如:

    List m;
    ...
    m.size();
    

    但是当你开始实例化时,你会使用一个实现子类来实现,例如:

    List m;
    ...
    m = new ArrayList();
    ...
    m.size();
    

    注意在实例化时,我们如何使用 ArrayList,而不是 List(它只是接口)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-05
      • 2013-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多