【问题标题】:Why can't we instantiate an abstract class in Java?为什么我们不能在 Java 中实例化一个抽象类?
【发布时间】:2014-03-08 00:19:47
【问题描述】:

我明白了:

  1. 因为抽象类本身没有任何东西,例如车辆,我们想要创建一个具体实现的对象,例如 Car、Bike 等。
  2. 抽象类的构造函数在对象链接期间被调用。
  3. 我们永远不能直接创建抽象类的对象,即使它包含构造函数并且所有方法都已实现。

但从编译器的角度来看,为什么 Java 会强制执行这些规则?

【问题讨论】:

  • 如果作者希望你能够实例化它,他们可以使它成为非抽象的。他们没有——即使他们确实实现了所有方法——这一事实是一种软件架构选择;他们告诉你他们不相信使用默认实现是有意义的。问他们为什么,或者接受它并创建一个子类。
  • 你不能这样做,因为作者将类标记为abstract,这是Java中这个词的一部分含义。
  • 因为Java语言是这样定义的。
  • @Raymond Chenon 在那个答案中,抽象类没有被实例化。抽象类的匿名子类被实例化。

标签: java oop inheritance constructor abstract-class


【解决方案1】:

在java中,除了少数情况外,一切都被表示为一个对象。当你要实例化类时(一个蓝图),你必须知道类成员变量、成员方法和构造函数的确切大小。由于某些/所有方法都是抽象的,并且 JVM 不知道大小。因此分配内存是没有用的。

但是如果我们将内存分配部分从 JVM 中移开并将此所有权分配给 USER,我们可以实现一些东西来克服这个问题。

【讨论】:

    【解决方案2】:

    抽象类不能使用 new 操作符来实例化。因为抽象可能有抽象方法,即没有任何主体(或实现)的方法。 因为一个对象不能有抽象方法,JVM不能分配抽象方法的内存

    【讨论】:

      【解决方案3】:

      您可以实例化一个抽象类。您只需要提供一个具体的子类。

      【讨论】:

        【解决方案4】:

        因为抽象类是一个不完整的类(不完整的意思是它包含没有主体和输出的抽象方法)我们不能创建实例或对象;就像你说的接口一样。

        【讨论】:

          【解决方案5】:

          因为 Java 限制了它,所以我们不能实例化抽象类。因为在一般情况下,抽象意味着不完整,所以我们不能将不完整的对象变成对象。我们必须在具体类中提供抽象类的完整实现。但是我们不能创建抽象类的对象。

          【讨论】:

          • 不..我不满意..请分享更多见解
          • 在 Singleton 类中使用私有构造函数以避免从其他地方创建对象
          【解决方案6】:

          很简单的原因 jvm 玩限制我们实例化抽象类和接口。

          假设编译器允许我们实例化两者都ok。

          所以假设我的抽象类包含 5 个抽象方法意味着只有方法原型没有方法体。

          所以我们知道每个方法调用都会在 jvm Java 堆栈区域中创建一个单独的堆栈 内存分配是基于方法结构发生的 并且在执行之后该堆栈正在销毁。

          所以如果我的方法不包含任何主体意味着jvm如何预测内存来分配该方法

          其次,如果没有主体意味着没有方法执行,因此它永远不会从您的 Java 堆栈区域中销毁,您可能会遇到 memoryout 错误。

          所以考虑到这两种情况编译器限制我们实例化接口和抽象类

          【讨论】:

            【解决方案7】:

            Java 不允许实例化抽象类的原因是合乎逻辑的。我们没有给出方法的定义,因此,如果它允许创建对象,则没有返回地址可以从堆栈中弹出函数,因此我们陷入困境。因此,它的逻辑只是不允许对象安装。

            【讨论】:

              【解决方案8】:

              抽象的自我告诉:存在于思想中或作为一个想法,但没有物理或具体的存在。 在 java 术语中,abstract 关键字定义,如果 abstract 出现在类名之前,则 JDK 告诉 JVM 丢弃该类对象初始化。 没错,抽象类可以有多个构造函数,但只能用于构造函数链接。

              【讨论】:

                【解决方案9】:

                抽象类不完整!作者将其标记为摘要是为了告诉您代码中缺少一些实现。作者已经完成了一些工作,但是您必须自己填写一些内容才能使其正常工作。 abstract 关键字确保没有人会意外启动这个不完整的类。

                想想修理一辆汽车。有人拆下了刹车片,打算在第二天更换。现在,为了防止有人意外驾驶这辆车(没有安装刹车),机械师在方向盘上安装了一个锁。这是一种防故​​障措施。

                【讨论】:

                  【解决方案10】:

                  你不能实例化抽象类,因为它只是为你的类提供一个扩展它的结构。

                  如果你想开始你的课程,那么为什么要将它定义为abstract

                  【讨论】:

                    【解决方案11】:

                    其实你可以——但前提是你实现了任何被声明为抽象或遗漏的方法。

                    /**
                     * A classic adaptor pattern.
                     *
                     * @param <P>
                     * @param <Q>
                     */
                    public static interface Adapter<P, Q> {
                    
                      public Q adapt(P p);
                    
                    }
                    
                    /**
                     * An I walks an iterator of one type but delivers items of a different type.
                     *
                     * Please fill in the `next()` method. Use an Adaptor for convenience.
                     *
                     * @param <S>
                     * @param <T>
                     */
                    public abstract static class I<S, T> implements Iterator<T> {
                    
                      protected final Iterator<S> it;
                    
                      public I(Iterator<S> it) {
                        this.it = it;
                      }
                    
                      @Override
                      public boolean hasNext() {
                        return it.hasNext();
                      }
                    
                      @Override
                      public void remove() {
                        it.remove();
                      }
                    
                    }
                    
                    /**
                     * Use an adaptor to transform one type into another.
                     *
                     * @param <S>
                     * @param <T>
                     */
                    public static class IA<S, T> extends I<S, T> {
                    
                      private final Adapter<S, T> adaptor;
                    
                      public IA(Iterator<S> it, Adapter<S, T> adaptor) {
                        super(it);
                        this.adaptor = adaptor;
                      }
                    
                      @Override
                      public T next() {
                        // Implement the abstract method on-the-fly.
                        return adaptor.adapt(it.next());
                      }
                    
                    }
                    

                    添加

                    IA 类实例化了I 抽象类的一个对象,并实现了I 类中缺少的next 方法。您实际上是在创建一个实现隐含抽象方法的匿名对象。

                    【讨论】:

                    • 这不是很有帮助:)
                    • 我看不出这与 OP 的要求有什么关系,或者它在哪里实例化一个抽象类(因为你不能这样做)
                    【解决方案12】:

                    rocketboy 展示了一些机械上的原因,但还有一个概念上的原因。

                    一个抽象类代表一个抽象概念。以您的车辆为例。您不能制造不是更具体的车辆。您可以拥有一套车辆,可以由 2004 corolla 和 '98 ford escorts 和 1984 cs36(一种游艇),mark 4 萤火虫级中程散货运输(带有稳定器的那个)制成,您可以将其中任何一个单独带上并称它们为车辆,但您不能拥有仅是车辆而不是其中之一或其他特定类型车辆的东西。

                    抽象类表示车辆等抽象概念。因此,实例化一个的想法是没有意义的,因为要实际实例化它,您需要知道您正在实例化什么。

                    【讨论】:

                    • 谢谢,我猜它更像是一个规则,为什么这是因为概念设计,因此使编译器强制错误。
                    • 除了表示一个实例化没有意义的概念(如此答案中给出的示例中的“车辆”)外,它还允许程序设计人员指定有关该概念所需的内容,因此可以帮助后来的程序员理解和扩展 Abstract 类。 AFAIK,如果程序设计者认为这是实现它的最佳方式,则不要求任何此类概念是抽象类-“车辆”或任何可以是超类并允许实例化的东西。但是语言设计者允许你这样做。
                    【解决方案13】:

                    据我所知,抽象类可能包含抽象(没有实现的空)方法。如果我们实例化一个对象并调用空方法,它将无法工作并且可能会导致问题,因此编译器会强制执行此规则。 有没有更深入的了解?

                    【讨论】:

                    • 但是我们可以有一个没有任何抽象方法的抽象类。那为什么要阻止实例化呢?
                    【解决方案14】:

                    您不能实例化接口或抽象类,因为它会违反面向对象的模型。 Read more

                    【讨论】:

                      【解决方案15】:

                      因为抽象类是一个骨架结构(如果可能的话,一个不完整的结构),因此术语抽象。

                      abstract class Person(){
                         abstract void Speak();
                      }
                      

                      意味着每个Person 都必须发言。这意味着每个人都应该知道如何说话(实现speak())。 new Person() 不能有,所以不允许。

                      【讨论】:

                      • 抽象类不需要抽象方法
                      • 是的,它没有。只是用来演示。
                      • OP 明确询问抽象类没有抽象方法(“即使它包含构造函数并且所有方法都已实现”)
                      【解决方案16】:

                      这不是技术限制,而是(正如您所指出的)合乎逻辑的限制。 Java(和许多其他语言)强制执行各种规则并不是因为它们不可能被打破,而是因为这是该语言的有意部分。

                      【讨论】:

                      • 我同意。有些对象根本不存在,它们是“抽象”术语。
                      • @eli iser :谢谢,我猜它更像是一个规则,为什么它是因为概念设计,因此使编译器强制错误......
                      猜你喜欢
                      • 1970-01-01
                      • 2011-07-05
                      • 1970-01-01
                      • 2014-09-08
                      • 1970-01-01
                      • 1970-01-01
                      • 2020-11-21
                      • 1970-01-01
                      相关资源
                      最近更新 更多