Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中,何时必须有默认构造函数和参数化构造函数?_Java_Constructor - Fatal编程技术网

在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);
    }
} 
将抛出一个错误,要求实现默认构造函数
  • 案例1:
    如果您不编写构造函数,则使用默认构造函数 将(由编译器)添加,您可以使用它创建对象。但是 如果您编写参数化构造函数,并希望创建对象 像

    ClassName ObjName=new ClassName()

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

  • 案例2(继承):如果您的子类构造函数没有 显式调用父类构造函数(在第一行中),然后 编译器会帮你做的

    class子类扩展父类{
    儿童班(){
    //编译器添加的super()。
    }
    }

    同样的事情

    若父类中并没有构造函数,将调用精细的默认构造函数(由编译器添加)

    但若parentclass有一个参数化的构造函数,那个么就并没有默认的构造函数,所以会出现错误

  • 当您有参数化构造函数和

  • 希望创建类似案例1的对象

  • 继承此类,不进行显式调用

    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-你能分享一下简单的例子吗?感谢插件架构的想法,我工作过的大多数插件都是内部插件