【问题标题】:How IIOException has no no-arg constructor?IIOException 如何没有无参数构造函数?
【发布时间】:2014-08-31 10:42:19
【问题描述】:

假设我们在 NoArgConstructorClass.java 文件中有一个类 NoArgConstructorClass

/* first example */
import javax.imageio.IIOException;

public class NoArgConstructorClass
{    
    public static void main(String[] args)
    {
        NoArgConstructorClass n = new NoArgConstructorClass();
        IIOException e = new IIOException();
    }
}

此代码编译产生错误:找不到适合 IIOException 的构造函数。

既然IIOException应该有一个无参构造函数(由编译器添加),那么IIOException没有无参构造函数是怎么做到的呢?

/** second example, showing that ClassB inherits a no-arg constructor from Object */
/** put in ConstructorChain.java */
public class ConstructorChain
{
    public static void main(String[] args)
    {
        ClassB b = new ClassB();
    }
}

/** put in ClassA.java */
public class ClassA
{
    public ClassA()
    {
        System.out.println("Class A");
    } 
}

/** put in ClassB.java */
public class ClassB
    extends ClassA
{
}

【问题讨论】:

    标签: java inheritance constructor arguments


    【解决方案1】:

    问。此代码编译产生错误:没有为 IIOException 找到合适的构造函数。

    如果您查看IIOException 的文档,您会发现它没有默认(无参数)构造函数。它有 2 个构造函数,并且都是参数化的(单参数和双参数)。这就是当您尝试使用无参数构造函数创建 IIOException 实例时出现编译错误的原因。


    问。既然IIOException应该从Object继承一个无参构造函数,那IIOException怎么没有无参构造函数呢?

    它不继承无参数构造函数。当一个类被继承时,您可以使用super() 添加对其超类构造函数的调用,或者编译器会这样做,以防您不这样做。所以IIOException 的构造函数看起来像这样。

    public IIOException(String message) {
        // if the below line is not present, the compiler adds it
        super(); // This calls the parent class (IOException) constructor and since there is a no-arg constructor there, its perfectly valid
        ... // other code
    }
    

    我现在重新阅读了您的问题两次,我认为您正在将编译器添加的默认无参数构造函数作为从父类继承的构造函数。

    正如JLS-8.8.9中提到的(感谢OP提供的链接),

    如果你有一个没有构造函数的类(有或没有 arg),编译器会自己添加一个默认的无参数构造函数。 但是如果你指定了一个带 arg 的构造函数并且没有指定一个无参数的构造函数,那么编译器不会为类添加一个默认的无参数的构造函数。我举个例子吧。

    class A {}
    

    您可以使用A a = new A() 实例化类A,因为即使您没有指定任何构造函数,默认的无参数构造函数也会添加到类中。

    但如果你的班级是这样的,

    class A {
        public A(int b) {
        }
    }
    

    在这种情况下,您只有一个参数构造函数。您现在可以仅使用此构造函数来实例化您的类,因为编译器不会向它添加默认的无参数构造函数,因为它已经有一个构造函数(带有一个参数)。因此,A a = new A(1) 可以工作,而A a = new A() 则不行。

    如果您希望能够创建这样的实例,A a = new A(),那么您需要显式向您的类添加一个无参数构造函数,就像这样

    class A {
        public A(int b) { // single argument constructor
        }
        public A() { // no argument constructor
        }
    }
    

    【讨论】:

    • 很高兴,您重新阅读了这个问题,并且做对了。所以,你的回答被接受了!
    【解决方案2】:

    如果您使用下面的代码而不是示例 2,则会产生编译错误。 IIOException 就是这样工作的。所以你会得到示例 1 中的编译错误。

    public class ConstructorChain
        {
            public static void main(String[] args)
            {
                ClassB b = new ClassB();
            }
        }
    class ClassA
    {
        public ClassA()
        {
            System.out.println("Class A");
        } 
    }
    
    /** put in ClassB.java */
     class ClassB
        extends ClassA
    {
         ClassB(String str)
         {
    
         }
    }
    

    【讨论】:

      【解决方案3】:

      如果一个类没有构造函数(如 ClassB 中),那么根据 Java 语言规范 8.8.9 "Default constructor": "如果一个类不包含构造函数声明那么一个没有形式参数的默认构造函数并且没有 throws 子句被隐式声明。"

      因此,如果该类至少有一个构造函数,那么它应该有自己的无参数构造函数声明才能真正拥有它。

      所以如果 ClassB 至少有一个构造函数

      /** put in ClassB.java */
      public class ClassB
          extends ClassA
      {
          public ClassB(String s)
          {
          }
      }
      

      那么除非明确定义,否则它将没有无参数构造函数:

      /** put in ClassB.java */
      public class ClassB
          extends ClassA
      {
          public ClassB()
          {
          }
      
          public ClassB(String s)
          {
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2023-03-12
        • 1970-01-01
        • 2011-11-24
        • 1970-01-01
        • 2014-06-30
        • 2015-02-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多