Java 为什么需要使用多个构造函数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37517522/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 19:24:56  来源:igfitidea点击:

Why would you need to use more than one constructor?

javaconstructor

提问by Tren46

I am learning Java as of right now and have just been learned what constructors are. I do not understand why you would need more than one constructor if you need to initialize all variables.

我现在正在学习 Java,刚刚了解了什么是构造函数。如果您需要初始化所有变量,我不明白为什么您需要多个构造函数。

采纳答案by Harish Vashist

A class can have multiple constructors, as long as their signature (the parameters they take) are not the same. You can define as many constructors as you need. When a Java class contains multiple constructors, we say that the constructor is overloaded (comes in multiple versions). This is what constructor overloading means, that a Java class contains multiple constructors.

一个类可以有多个构造函数,只要它们的签名(它们采用的参数)不同即可。您可以根据需要定义任意数量的构造函数。当一个 Java 类包含多个构造函数时,我们说构造函数是重载的(有多个版本)。这就是构造函数重载的含义,即一个 Java 类包含多个构造函数。

Having said that, it is completely dependent upon your implementation whether or not you want to create more than one constructor in your class but having more than one constructor can ease your life in many instances. Suppose below class doesn't have a default constructor:

话虽如此,您是否想在类中创建多个构造函数完全取决于您的实现,但在许多情况下,拥有多个构造函数可以让您的生活更轻松。假设下面的类没有默认构造函数:

public class Employee {

    private int age;
    private String name;

    Employee(int age, String name){
        this.age=age;
        this.name=name;     
    }
}

So, while creating object of this class user would not be able to do so until he has age and name parameters handy which restricts the true functionality of Java objects as Objects' state should be able to be modified and populated at any time once initialized.

因此,在创建此类对象时,用户将无法这样做,直到他手头有年龄和名称参数,这限制了 Java 对象的真正功能,因为对象的状态应该能够在初始化后随时修改和填充。

回答by Do Nhu Vy

Per constructor has specific purpose. Sometimes we need more than one constructor (special in Entity domain case, when use ORM)

每个构造函数都有特定的用途。有时我们需要多个构造函数(特别是在实体域的情况下,当使用 ORM 时)

For example:

例如:

  • Empty constructor (no arguments) for reflection,

  • Constructor has argument(s) for create new instance (A a = new A('foo', 'bar');).

  • 用于反射的空构造函数(无参数),

  • 构造函数具有用于创建新实例 ( A a = new A('foo', 'bar');) 的参数。

These're overload method(s).

这些是重载方法。

Reality example:

现实例子:

package sagan.blog;

import com.fasterxml.Hymanson.annotation.JsonIgnore;
import org.hibernate.annotations.Type;
import org.springframework.util.StringUtils;
import sagan.team.MemberProfile;

import javax.persistence.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

/**
 * JPA Entity representing an individual blog post.
 */
@Entity
@SuppressWarnings("serial")
public class Post {

    private static final SimpleDateFormat SLUG_DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd");

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(cascade = CascadeType.PERSIST, optional = false)
    private MemberProfile author;

    @Column(nullable = false)
    private String title;

    @Column(nullable = false)
    @Enumerated(EnumType.STRING)
    private PostCategory category;

    @Column(nullable = false)
    @Enumerated(EnumType.STRING)
    private PostFormat format;

    @Column(nullable = false)
    @Type(type = "text")
    private String rawContent;

    @Column(nullable = false)
    @Type(type = "text")
    private String renderedContent;

    @Column(nullable = false)
    @Type(type = "text")
    private String renderedSummary;

    @Column(nullable = false)
    private Date createdAt = new Date();

    @Column(nullable = false)
    private boolean draft = true;

    @Column(nullable = false)
    private boolean broadcast = false;

    @Column(nullable = true)
    private Date publishAt;

    @Column(nullable = true)
    private String publicSlug;

    @ElementCollection
    private Set<String> publicSlugAliases = new HashSet<>();

    @SuppressWarnings("unused")
    private Post() {
    }

    public Post(String title, String content, PostCategory category, PostFormat format) {
        this.title = title;
        this.rawContent = content;
        this.category = category;
        this.format = format;
    }

    /* For testing only */
    public Post(Long id, String title, String content, PostCategory category, PostFormat format) {
        this(title, content, category, format);
        this.id = id;
    }

    public Long getId() {
        return id;
    }

    public MemberProfile getAuthor() {
        return author;
    }

    public void setAuthor(MemberProfile author) {
        this.author = author;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public PostCategory getCategory() {
        return category;
    }

    public void setCategory(PostCategory category) {
        this.category = category;
    }

    public PostFormat getFormat() {
        return format;
    }

    public void setFormat(PostFormat format) {
        this.format = format;
    }

    public String getRawContent() {
        return rawContent;
    }

    public void setRawContent(String rawContent) {
        this.rawContent = rawContent;
    }

    public String getRenderedContent() {
        return renderedContent;
    }

    public void setRenderedContent(String renderedContent) {
        this.renderedContent = renderedContent;
    }

    public String getRenderedSummary() {
        return renderedSummary;
    }

    public void setRenderedSummary(String renderedSummary) {
        this.renderedSummary = renderedSummary;
    }

    public Date getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(Date createdAt) {
        this.createdAt = createdAt;
    }

    public Date getPublishAt() {
        return publishAt;
    }

    public void setPublishAt(Date publishAt) {
        this.publishAt = publishAt;
        publicSlug = publishAt == null ? null : generatePublicSlug();
    }

    public boolean isDraft() {
        return draft;
    }

    public void setDraft(boolean draft) {
        this.draft = draft;
    }

    public void setBroadcast(boolean isBroadcast) {
        broadcast = isBroadcast;
    }

    public boolean isBroadcast() {
        return broadcast;
    }

    @JsonIgnore
    public boolean isScheduled() {
        return publishAt == null;
    }

    @JsonIgnore
    public boolean isLiveOn(Date date) {
        return !(isDraft() || publishAt.after(date));
    }

    public String getPublicSlug() {
        return publicSlug;
    }

    public void addPublicSlugAlias(String alias) {
        if (alias != null) {
            this.publicSlugAliases.add(alias);
        }
    }

    @JsonIgnore
    public String getAdminSlug() {
        return String.format("%s-%s", getId(), getSlug());
    }

    private String generatePublicSlug() {
        return String.format("%s/%s", SLUG_DATE_FORMAT.format(getPublishAt()), getSlug());
    }

    @JsonIgnore
    private String getSlug() {
        if (title == null) {
            return "";
        }

        String cleanedTitle = title.toLowerCase().replace("\n", " ").replaceAll("[^a-z\d\s]", " ");
        return StringUtils.arrayToDelimitedString(StringUtils.tokenizeToStringArray(cleanedTitle, " "), "-");
    }

    @Override
    public String toString() {
        return "Post{" + "id=" + id + ", title='" + title + '\'' + '}';
    }
}

Class Posteven has 3 constructorsnamed Post(){...}

Post甚至有3 个命名的构造函数Post(){...}

Source: https://github.com/spring-io/sagan/blob/master/sagan-common/src/main/java/sagan/blog/Post.java

来源:https: //github.com/spring-io/sagan/blob/master/sagan-common/src/main/java/sagan/blog/Post.java

回答by Zero

To put it simply, you use multiple constructors for convenience (1st example) or to allow completely different initialization methods or different source types (2nd example.

简而言之,为了方便起见(第一个示例)或允许完全不同的初始化方法或不同的源类型(第二个示例),您可以使用多个构造函数。

You might need multiple constructors to implement your class to simply allow omitting some of the parameters that are already setup:

您可能需要多个构造函数来实现您的类,以允许省略一些已经设置的参数:

//The functionality of the class is not important, just keep in mind parameters influence it.
class AirConditioner{
   enum ConditionerMode{
      Automatic, //Default
      On,
      Off
   }
   public ConditionerMode Mode; //will be on automatic by default.
   public int MinTemperature = 18;
   public int MaxTemperature = 20;

   public AirConditioner(){ //Default constructor to use default settings or initialize manually.
      //Nothing here or set Mode to Automatic. 
   }

   //Mode
   public AirConditioner(ConditionerMode mode){ //Setup mode, but leave the rest at default
      Mode = mode;
   }
   //setup everything.
   public AirConditioner(ConditionerMode mode, int MinTemp, int MaxTemp){
      Mode = mode;
      MinTemperature = MinTemp;
      MaxTemperature = MaxTemp;
   }
}


Another example is when different constructors follow different procedures to initialize the variables. For instance you could have a data table that simply displays a table of text. The constructor could get the data from either database OR a file:

另一个例子是当不同的构造函数遵循不同的过程来初始化变量时。例如,您可以有一个仅显示文本表的数据表。构造函数可以从数据库或文件中获取数据:

class DataTable{
   public DataTable(){} //Again default one, in case you want to initialize manually

   public DataTable(SQLConnection con, SQLCommand command){
      //Code to connect to database get the data and fill the table
   }

   public DataTable(File file){
      //Code to read data from a file and fill the table
   }
}

回答by Dun

So, recall that the purpose of the constructor is to initialize (give them values). So think of this model:

所以,回想一下构造函数的目的是初始化(给它们值)。所以想想这个模型:

public class Car{
           private String model; //Objects are null 
           private int year; // year = 0 
           Car(String model, int year ){
            this.model = model;
            this.year = year; 
        }
    }

The Car object you create needs values for the model and the year. It would be great if you could just create a dummy car with just default values for each field, or take a string that looks like this:

您创建的 Car 对象需要模型和年份的值。如果您可以为每个字段创建一个仅具有默认值的虚拟汽车,或者采用如下所示的字符串,那就太好了:

"Ford 2016 or "Ford" and "2016"and create a Car object.

"Ford 2016 or "Ford" and "2016"并创建一个 Car 对象。

So, just create two more constructors with different signatures that accomplish that task.

因此,只需创建两个具有不同签名的构造函数即可完成该任务。

Also, imagine we have another String field called owner. The owner of a car may not be know at the creation of this object, but your program may be able to function without it. So, we can use the same constructor above and the Car object's owner field will be set to null.

另外,假设我们有另一个名为 owner 的 String 字段。创建此对象时,汽车的所有者可能不知道,但您的程序可能可以在没有它的情况下运行。因此,我们可以使用上面相同的构造函数,并且 Car 对象的 owner 字段将设置为 null。

That's the purpose for multiple constructors. To give the programmer flexibility on saying whatan object can be created from and whichvariables need to be initialized in the first place.

这就是多个构造函数的目的。让程序员可以灵活地说明可以从哪些对象创建对象以及首先需要初始化哪些变量。

You may also find this useful:

您可能还会发现这很有用:

enter image description here

在此处输入图片说明