Java实体 - 为什么我需要一个空的构造函数?

时间:2013-08-07 09:04:45

标签: java jpa entity

这对你来说可能听起来很愚蠢, 但为什么我需要在@Entity s中定义一个空构造函数?

我看到的每个教程都说:每个实体都需要一个空的构造函数。

但是Java总是给你一个默认的不可见的空构造函数(如果你不重新定义它)。

感谢。

修改

我认为存在语义问题。 我对“需要”所理解的是写作。

含义:总是在你的实体中写一个空的构造函数。

示例:

@Entity
public class MyEntity implements Serializable {

   @Id
   private String str;

   public MyEntity(){}

   //here getter and setter
}

但是当你不重新定义它时,Java总会给你这个空的构造函数(用参数写另一个)。

在这种情况下,编写这个空构造函数似乎没用。

8 个答案:

答案 0 :(得分:36)

需要空构造函数来通过持久性框架的反射来创建新实例。如果您没有为该类提供任何其他带有参数的构造函数,则不需要提供空构造函数,因为每个默认值都会得到一个。

您还可以使用@PersistenceConstructor注释,如下所示

@PersistenceConstructor
public Movie(Long id) {
    this.id = id;
}

如果您的项目中存在Spring Data,则初始化您的实体。因此,您也可以避免使用空构造函数。

答案 1 :(得分:24)

  

但java总是给你一个默认的不可见的空构造函数(如果你   不要重新定义一个。)

只有在类中未提供任何构造函数时,此语句才为真。如果在类中提供了参数构造函数,那么jvm将不会添加无参构造函数。

答案 2 :(得分:5)

除非为实体提供另一个构造函数,否则不必显式定义默认构造函数。如果您提供另一个构造函数,除了具有默认构造函数签名的构造函数之外,将不会创建默认构造函数。

由于JPA实现依赖于默认构造函数的存在,因此必须包含将被省略的默认构造函数。

答案 3 :(得分:3)

当您指定“JPA”标记时,我假设您的问题仅适用于JPA,而不适用于空构造函数。

Persitence框架经常使用反射,更具体地说是Class<T>.newInstance()来实例化你的对象,然后通过内省调用getters / setter来设置字段。

这就是为什么你需要一个空的构造函数和getter / setter。

请参阅this StackOverflow question about empty constructors in Hibernate.

答案 4 :(得分:1)

实际上你不需要写它。你默认拥有它。有时您可以创建private构造函数以防止用户使用默认

public class MyClass{

private MyClass(){} 

} 

对于singelton模式,例如,您可以阻止使用默认构造函数。

有时候,当你使用Gson插件将String Json数据转换为Object时,它需要编写默认构造函数,否则它不起作用

答案 5 :(得分:0)

如果您的类有参数构造函数,Java并不总是为您提供默认的不可见空构造函数,您必须自己定义空构造函数。

答案 6 :(得分:0)

所有答案都很好。

但是让我们谈谈代码。遵循以下代码片段将使您更加清晰。

PersonWithImplicitConstructor.java

public class PersonWithImplicitConstructor {
    
    private int id;
    
    private String name;

}

首先,我们必须编译.java文件

javac PersonWithImplicitConstructor.java

然后将生成类文件。

在该类文件的顶部运行javap将为您提供以下信息。

javap PersonWithImplicitConstructor.class

Compiled from "PersonWithImplicitConstructor.java"
public class PersonWithImplicitConstructor {
  public PersonWithImplicitConstructor();
}

注意::如果您想了解更多信息,可以在-p上使用javap标志。

下一个Java文件将仅具有参数化的构造函数。

PersonWithExplicitConstructor.java

public class PersonWithExplicitConstructor {
    
    private int id;
    
    private String name;

    public PersonWithExplicitConstructor(int id, String name) {
        this.id = id;
        this.name = name;
    }
}

javac PersonWithExplicitConstructor.java

javap PersonWithExplicitConstructor.class

Compiled from "PersonWithExplicitConstructor.java"
public class PersonWithExplicitConstructor {
  public PersonWithExplicitConstructor(int, java.lang.String);
}

PersonWithBothConstructors.java

public class PersonWithBothConstructors {

    private int id;
    
    private String name;

    public PersonWithBothConstructors() {

    }

    public PersonWithBothConstructors(int id, String name) {
        this.id = id;
        this.name = name;
    }
    
}

javac PersonWithBothConstructors.java

javap PersonWithBothConstructors.class

Compiled from "PersonWithBothConstructors.java"
public class PersonWithBothConstructors {
  public PersonWithBothConstructors();
  public PersonWithBothConstructors(int, java.lang.String);
}

答案 7 :(得分:-1)

从JPA标记中,我认为您正在使用Java bean。每个bean都需要具有以下属性:

  1. 所有主要实例变量的getter和setter。

  2. 空构造函数。

  3. 其所有实例变量最好为private

  4. 因此声明:“每个实体都需要一个空构造函数”。