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

时间:2009-12-07 11:53:16

标签: java constructor this abstract

有人可以指出我误解了什么吗?

我有两个类,一个抽象和一个混凝土,如下:

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;摘要没有参考   构造函数叫。
  2)等级=   具体; Abstract的1-arg构造函数   调用。
  3)Class = Concrete;   Concrete的1-arg构造函数叫。

我的问题是:为什么不从Abstract的String arg构造函数调用this()在Concrete上调用这个no-arg构造函数?或者,或许更有针对性,有没有办法让Abstract的String arg构造函数调用Concrete上的no-arg构造函数,允许构造函数的“正确”链接?

5 个答案:

答案 0 :(得分:7)

否 - 构造函数链接总是横向(相同类型)或向上(到父类型)。

不要忘记调用必须在编译时解决 - 并且Abstract不知道其他类将从中派生出什么,或者它们是什么构造函数我会的。

可以Abstract构造函数中调用虚拟方法,并在Concrete中覆盖该方法...但我会敦促您这样做。特别是,Concrete的构造函数体尚未执行,变量初始化器也不会 - 因此它无法对Concrete特定状态执行任何操作。有一些非常特定的情况,这是正确的事情,但它们很少见,应谨慎处理。

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

答案 1 :(得分:1)

这就是它的方式(如Jon Skeet所详述)。

您可以将以下块添加到Concrete:

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

与默认构造函数相反,始终会调用inizializer块:

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 :(得分:1)

以下是post,它关注的是抽象类的需要及其工作原理。这对你有帮助。

答案 3 :(得分:1)

您必须知道子类始终隐藏在父类中。您不能像在子类中那样直接调用子类的方法或构造函数。

答案 4 :(得分:0)

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

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
}