在Java中,何时必须有默认构造函数和参数化构造函数?
很多时候我都会遇到一个异常,说“默认构造函数的实现丢失了”。很多时候,参数化构造函数的定义本身就可以完成一切。我想知道这是在什么条件下发生的 编译器从不强制默认构造函数的存在。您可以拥有任何类型的构造函数 对于某些库或框架,类可能需要有默认构造函数,但编译器并不强制这样做 您可能看到的问题是,如果您有一个带有自定义构造函数的类,而构造函数体中没有隐式的在Java中,何时必须有默认构造函数和参数化构造函数?,java,constructor,Java,Constructor,很多时候我都会遇到一个异常,说“默认构造函数的实现丢失了”。很多时候,参数化构造函数的定义本身就可以完成一切。我想知道这是在什么条件下发生的 编译器从不强制默认构造函数的存在。您可以拥有任何类型的构造函数 对于某些库或框架,类可能需要有默认构造函数,但编译器并不强制这样做 您可能看到的问题是,如果您有一个带有自定义构造函数的类,而构造函数体中没有隐式的super()调用。在这种情况下,编译器将引入对超级类默认构造函数的调用。如果超类没有默认构造函数,那么您的类将无法编译 public class
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
}
}
通常,当类的实例通过反射创建时(例如在反序列化时),会发生这种情况。如果您的类是可序列化的,或者它的实例可以通过反射机制创建,则应该定义默认构造函数。如果类中没有构造函数,则在编译时添加一个默认构造函数
@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);
}
}
若类中存在任何一个参数化构造函数,则在编译时不会添加默认构造函数
所以,如果您的程序有任何包含参数的构造函数,并且没有指定默认构造函数,那么您将无法使用默认构造函数创建该类的对象
@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);
}
}
例如:
正如Joachim Sauer所说,在使用spring等框架时,除了参数化构造函数之外,还需要提供默认构造函数,这一点很重要。因为如果您希望通过在另一个类中的依赖项注入来注入类对象,那么该类应该具有默认构造函数
@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);
}
}
否则依赖注入将失败
这只是我遇到默认构造函数重要性的一个场景,现在还不完全清楚您所说的是运行时异常还是编译错误 只有当您的代码(或您的代码调用的某些库代码)尝试使用反射创建某个类的实例,并且意外尝试使用不存在的构造函数时,才会发生运行时异常。(我怀疑异常消息是否会使用术语“默认构造函数”…) 编译错误的发生是因为您显式或隐式地试图调用不存在的“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.
}
}
前两个例子很明显调用了无参数构造函数
@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);
}
}
最后一个示例调用no args构造函数,因为如果在构造函数开始时没有显式的super
或this
“调用”,JLS表示将调用super()
。。。在所有情况下,除了对象的构造函数
最后,回答标题中的问题: 在Java中,何时必须有默认构造函数和参数化构造函数 严格地说,从来没有强制要求使用默认构造函数。必须有一个无args构造函数(显式声明或默认)。。。仅当显式或隐式调用它时
(可能有库/框架假设您的类没有args构造函数,但这超出了我们可以回答的范围。此外,这样的假设可以反射地创建实例……我已经介绍过了。)编译代码时,编译器将添加默认构造函数,但在代码中声明参数化构造函数时,默认构造函数将被忽略
当使用参数化构造函数重载默认构造函数时,在使用默认构造函数而不是参数化构造函数创建对象时,代码中必须有默认构造函数。使用框架时需要默认构造函数(例如:Spring framework)您需要创建Springbean的实例,而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);
}
}
将抛出一个错误,要求实现默认构造函数
如果您不编写构造函数,则使用默认构造函数 将(由编译器)添加,您可以使用它创建对象。但是 如果您编写参数化构造函数,并希望创建对象 像
ClassName ObjName=new ClassName()代码>
然后您必须手动添加默认构造函数
class子类扩展父类{
儿童班(){
//编译器添加的super()。
}
}
同样的事情
若父类中并没有构造函数,将调用精细的默认构造函数(由编译器添加)
但若parentclass有一个参数化的构造函数,那个么就并没有默认的构造函数,所以会出现错误super(参数,…)代码>
在子类构造函数的第一行中
@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);
}
}
你从哪里得到这个信息?请发布完整准确的错误消息。唯一可以想到的是,如果类是在runtime@MadProgrammer-你能分享一下简单的例子吗?感谢插件架构的想法,我工作过的大多数插件都是内部插件