什么时候必须在Java中使用默认构造函数和参数化构造函数?

时间:2012-10-09 10:48:11

标签: java constructor

很多时候我有一个例外,说“缺少默认构造函数的实现”。很多时候,参数化构造函数的定义单独执行所有操作。我想知道这种情况发生在哪种情况下。

8 个答案:

答案 0 :(得分:4)

编译器不会强制存在默认构造函数。您可以根据需要使用任何类型的构造函数。

对于某些框架,类可能需要具有默认构造函数,但编译器不强制执行此操作。

您可能会遇到的问题是,如果您的类具有自定义构造函数,并且您的构造函数体中没有隐式super()调用。在这种情况下,编译器将引入对超类默认构造函数的调用。如果超类没有默认构造函数,那么你的类将无法编译。

public class MyClass extends ClassWithNoDefaultConstructor
    public MyClass() {
        super(); //this call will be added by the compiler if you don't have any super call here
        // if the super class has no default constructor the above line will not compile
        // and removing it won't help either because the compiler will add that call
    }
}

答案 1 :(得分:2)

AS Joachim Sauer 说,当你使用像spring这样的框架时,除了你的参数化构造函数之外,还需要提供默认构造函数。因为如果你想通过依赖注入在另一个类中注入你的类对象,那么该类应该有默认的构造函数。

否则您的依赖注入将失败。

只有一个场景我遇到了默认构造函数的重要性

答案 2 :(得分:2)

目前尚不清楚您是在讨论运行时异常还是编译错误。

只有当您的代码(或代码调用的某些库代码)尝试使用反射来创建某个类的实例,并且意外地尝试使用不存在的构造函数时,才会发生运行时异常。 (我怀疑异常消息会使用术语“默认构造函数”......)

发生编译错误是因为您显式或隐式地尝试调用不存在的“no args”构造函数。有三种情况'

// case #1
new Foo();

// case #2
public Bar extends Foo {
  public Bar() {
    super();
  }
}

// case #3
public Bar extends Foo {
  public Bar() {
    // no explicit 'this' or 'super' call.
  }
}

前两个例子显然是在调用no-args构造函数。

最后一个示例调用no-args构造函数,因为如果在构造函数的开头没有显式的superthis“call”,则JLS会调用{除了super()的构造函数之外,所有情况下都会发生{1}}。


最后,您回答标题中的问题:

  

什么时候必须在Java中使用默认构造函数和参数化构造函数?

严格地说,拥有默认构造函数绝不是强制性的。只有在显式或隐式调用它时,必须有 no args 构造函数(显式声明或默认)...

(可能存在假设你的类具有无参数构造函数的库/框架,但这超出了我们可以回答的范围。此外,这样的假设将是这样的可以反思地创建实例......我已经涵盖了它。)

答案 3 :(得分:1)

通常,当通过反射创建类的实例时(例如,在反序列化时),可能会发生这种情况。如果您的类是Serializable或其实例可以通过反射机制创建,则应该定义默认构造函数。

答案 4 :(得分:1)

如果类中没有构造函数,则在编译时添加一个默认构造函数。

如果类中存在任何一个参数化构造函数,则在编译时不会添加默认构造函数。

因此,如果您的程序包含任何包含参数的构造函数,并且未指定默认构造函数,那么您将无法使用Default构造函数创建该类的对象。

例如:

class A{

A(int a){}

}

A a = new A() -----> Error.

-------------------------------------------------------

class A{

A(int a){}

A(){}

}

A a = new A() -----> It will work.

-----------------------------------------------------------

class A{

}

A a = new A() -----> It will work.

答案 5 :(得分:1)

  • 情况1:
    如果您不编写构造函数,则默认构造函数 将被添加(由编译器),您可以使用它创建对象。但 如果您编写参数化的构造函数,并想创建对象 喜欢

    ClassName ObjName = new ClassName();

    然后您必须手动添加默认构造函数。

  • 案例2(继承):如果您的子类构造函数不创建
    显式调用父类构造函数(在第一行本身),然后 编译器会为您完成。

    class ChildClass extends ParentClass{ ChildClass(){ //super() added by compiler. } }

    现在一样,

    如果父类中没有构造函数,则将调用默认的默认构造函数(由编译器添加)。

    但是如果父类具有参数化的构造函数,则没有默认的构造函数,因此会出现错误。

  • 具有参数化构造函数和

    1. 想要创建类似情况1的对象。

    2. 继承此类并且不进行显式调用

      super(parameter,...);

      ChildClass构造函数的第一行。

答案 6 :(得分:0)

编译器将在编译代码时添加默认构造函数,但是当您在代码中声明参数化构造函数时,将省略默认构造函数。

当使用参数化构造函数重载默认构造函数时,在使用默认构造函数而不是参数化构造函数创建对象时,必须在代码中使用默认构造函数。

答案 7 :(得分:0)

使用框架(例如:Spring框架)时需要默认构造函数,在该框架中需要创建Spring bean的实例,并且bean类仅具有参数化构造函数。

@Component
public class Bank {
    private String bankName;
    public Bank(String bankName){
        this.bankName = bankName;
    }
    @Override
    public String toString() {
    return this.bankName;
   }
}

public class Test {
    public static void main(String[] args) {
        ApplicationContext context = new 
AnnotationConfigApplicationContext(SpringConfig.class);
        Bank bank = context.getBean(Bank.class);    
        System.out.println(bank);
    }
} 

会抛出错误,要求实现默认构造函数