有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java:抽象类构造函数和this()

有人能指出我的误解吗

我有两个类,一个抽象类和一个具体类,如下所示:

public abstract class Abstract
{
    protected static int ORDER = 1;

    public static void main (String[] args)
    {
        Concrete c = new Concrete("Hello");
    }

    public Abstract()
    {
        Class c = this.getClass();
        System.out.println(ORDER++ + ": Class = " 
            + c.getSimpleName() 
            + "; Abstract's no-arg constructor called.");
    }

    public Abstract(String arg)
    {
        this();
        Class c = this.getClass();
        System.out.println(ORDER++ + ": Class = " 
            + c.getSimpleName() 
            + "; Abstract's 1-arg constructor called.");
    }
}

public class Concrete extends Abstract
{
   public Concrete()
   {
      super();
      Class c = this.getClass();
      System.out.println(ORDER++ + ": Class = " 
          + c.getSimpleName() 
          + "; Concrete's no-arg constructor called.");
   }

   public Concrete(String arg)
   {
      super(arg);
      Class c = this.getClass();
      System.out.println(ORDER++ + ": Class = " 
          + c.getSimpleName() 
          + "; Concrete's 1-arg constructor called.");
   }
}

当我运行此命令时,会得到以下输出:

1) Class = Concrete; Abstract's no-arg constructor called.
2) Class = Concrete; Abstract's 1-arg constructor called.
3) Class = Concrete; Concrete's 1-arg constructor called.

我的问题是:为什么抽象的字符串arg构造函数对this()的调用不调用具体的无arg构造函数?或者,也许更确切地说,有没有办法让抽象的字符串arg构造函数调用具体的无arg构造函数,从而允许构造函数的“正确”链接


共 (5) 个答案

  1. # 1 楼答案

    事情就是这样(Jon Skeet详细介绍了这一点)

    不过,您可以在混凝土中添加一个init块:

    {
      Class c = this.getClass();
      System.out.println(ORDER++ + ": Class = " 
      + c.getSimpleName() 
       + "; Concrete's init block called.");
    }
    

    与默认构造函数不同,Inalizalizer块始终被调用:

    1: Class = Concrete; Abstract's no-arg constructor called.
    2: Class = Concrete; Abstract's 1-arg constructor called.
    3: Class = Concrete; Concrete's init block called.
    4: Class = Concrete; Concrete's 1-arg constructor called.
    
  2. # 2 楼答案

    处理这个问题的最佳方法通常是让一个类的所有构造函数都使用一个公共构造函数,即:

    public Abstract() {
      this(null);
    }
    public Abstract(String arg) {
      // do all Abstract init here
    }
    
    public Concrete() {
      this(null);
    }
    public Concrete(String arg) {
      super(arg);
      // do all Concrete init here
    }
    
  3. # 3 楼答案

    否-构造函数链接总是从侧面(在同一类型中)或向上(到父类型)

    不要忘记,调用必须在编译时解析Abstract不知道其他类将从中派生什么,或者它们将拥有什么构造函数

    可以调用Abstract构造函数中的虚拟方法,并在Concrete中重写该方法。。。但我劝你不要那样做。特别是,Concrete的构造函数体尚未执行,变量初始值设定项也不会执行,因此它无法处理Concrete特定的状态。有一些非常特殊的情况下,这是正确的做法,但它们很罕见,应该谨慎处理

    你到底想做什么?通常,我发现最好是有许多“横向”链指向一个具有“向上”链的构造函数

  4. # 4 楼答案

    下面是post,重点介绍抽象类的需求以及它是如何工作的。愿这对你有帮助

  5. # 5 楼答案

    您应该知道子类总是对父类隐藏的。不能像在子类中那样直接调用子类的方法或构造函数