Java Setter 方法或构造函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19359548/
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-12 16:28:16  来源:igfitidea点击:

Setter methods or constructors

javaconstructorsetter

提问by ssayyed

so far I have seen two approaches of setting a variable's value in Java. Sometimes a constructor with arguments is used, others setter methods are used to set the value of each variable.

到目前为止,我已经看到了两种在 Java 中设置变量值的方法。有时使用带参数的构造函数,其他 setter 方法用于设置每个变量的值。

I know that a constructor initialises an instance variable inside a class once a class is instantiated using the "new" Keyword.

我知道,一旦使用“new”关键字实例化了一个类,构造函数就会在一个类中初始化一个实例变量。

But when do we use constructors and when do we use setters?

但是我们什么时候使用构造函数,什么时候使用 setter 呢?

采纳答案by SudoRahul

You should use the constructor approach, when you want to create a new instance of the object, with the values already populated(a ready to use object with value populated). This way you need not explicitly call the setter methods for each field in the object to populate them.

当您想要创建对象的新实例时,您应该使用构造函数方法,其中已经填充了值(填充了值的准备使用的对象)。这样你就不需要为对象中的每个字段显式调用 setter 方法来填充它们。

You set the value using a setter approach, when you want to change the value of a field, after the object has been created.

当您想在创建对象后更改字段的值时,您可以使用 setter 方法设置该值。

For example:-

例如:-

MyObject obj1 = new MyObject("setSomeStringInMyObject"); // Constructor approach
// Yippy, I can just use my obj1, as the values are already populated
// But even after this I can change the value
obj1.setSomeString("IWantANewValue"); // Value changed using setter, if required.
..
MyObject obj2 = new MyObject();
obj2.setSomeString("setSomeStringNow"); // Setter approach
// values weren't populated - I had to do that. Sad :(

And as Axel mentioned, if you want to create immutable objects, you cannot use setter-methods approach. I won't say everything has to be initialised in the constructor because different approaches exist, like lazy-evaluation which can be used even with immutable objects.

正如 Axel 所提到的,如果你想创建不可变的对象,你不能使用 setter-methods 方法。我不会说所有的东西都必须在构造函数中初始化,因为存在不同的方法,比如延迟评估,它甚至可以用于不可变对象

回答by Kasper Franz

In most cases i use both of them :) (since you 9/10 times want to come back and edit something (and that isn't a good practive to make a new instance of it)

在大多数情况下,我同时使用它们 :)(因为您有 9/10 次想要回来编辑某些内容(这不是制作它的新实例的好方法)

I normally make something like tihs

我通常做类似的东西

public class User {

    private int id;
    private String initials;
    private String firstName;
    private String lastName;
    private String email;

    public User() {
        this(0, "", "", "");
    }

    public User(int id, String firstName, String lastName, String email) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
    }
   // Getters and setters should be here
}

And when you want to edit something with it you can just use the setters, (a good thing if you for example is saving your users in a ArrayList, then you can just get the object from the arraylist and just set the field you wanna edit, instead of making a brand new object of it :)

当你想用它编辑一些东西时,你可以只使用 setter,(如果你将用户保存在 ArrayList 中,那么你可以从 arraylist 中获取对象并设置你想要编辑的字段,这是一件好事,而不是制作一个全新的对象:)

回答by Cold

You can combine the two aproaches. Inside the constructor you can invoke the setters of instace variables. Something like:

您可以结合使用这两种方法。在构造函数中,您可以调用实例变量的设置器。就像是:

public class TestClass {
    private String someField;

    public TestClass(String someField) {
        setSomeField(someField);
    }

    public String getSomeField() {
        return someField;
    }

    public void setSomeField(String someField) {
        this.someField = someField;
    } 
}

回答by Evgeniy Dorofeev

If you want to have an immutable class use constructor otherwise use setters.

如果你想要一个不可变的类使用构造函数,否则使用 setter。

回答by hmir

Say we have a class, named Counter:

假设我们有一个名为 Counter 的类:

public class Counter{
    int count;
    //constructor
    public Counter(int c){
        count = c;
    }
    public void setCounter(int newCounter){
        count = newCounter;
    }
}

In the class above, when you want to create a newCounter object, you would use a constructor and set the count variable within that. like so:

在上面的类中,当你想创建一个新的Counter 对象时,你将使用一个构造函数并在其中设置 count 变量。像这样:

Counter myCounter = new Counter(1);

If you want to change the count variable during runtime, you would use the setter method:

如果要在运行时更改计数变量,可以使用 setter 方法:

myCounter.setCounter(2);

回答by eatSleepCode

We use the approach depending on the scenario.

我们根据场景使用该方法。

  1. If we have set of values while instantiating object of the class then at that time we will use constructor approach.

  2. When we don't know the set of values while creating instance of the object at that time we will use setter approach.

  1. 如果我们在实例化类的对象时有一组值,那么那时我们将使用构造函数方法。

  2. 当我们在创建对象实例时不知道值集时,我们将使用 setter 方法。

回答by sgp15

It depends on application domain and purpose of the class in it.

这取决于应用程序域和其中类的用途。

Java beans normally have a no arg constructor and getter/setters for relevant member variables. There are advantages to this approach as Java beans are supported out of the box in many frameworks like Struts and Spring.

Java bean 通常没有 arg 构造函数和相关成员变量的 getter/setter。这种方法有很多优点,因为在许多框架(如 Struts 和 Spring)中都支持开箱即用的 Java bean。

A class can also enforce mandatory availability of values by having such variables passed as parameters to a base constructor. And non-mandatory values can be set through other convenience constructors or setter methods.

类还可以通过将此类变量作为参数传递给基本构造函数来强制强制使用值。并且可以通过其他方便的构造函数或 setter 方法设置非强制值。

On the other hand immutable classes can have constructors but require absence methods that modify its state including setters.

另一方面,不可变类可以有构造函数,但需要缺席方法来修改其状态,包括 setter。

Overall, such decisions can be made with consideration to overall design of application, frameworks1it runs in, contract it must enforce, etc.

总的来说,可以在考虑应用程序的整体设计、它运行的框架1、它必须执行的合同等的情况下做出这样的决定。

1 - Although, its recommended that class design should be independent of frameworks. Good frameworks like Spring don't enforce such requirements.

1 - 虽然,它建议类设计应该独立于框架。像 Spring 这样的优秀框架不会强制执行此类要求。

回答by Sushil kumawat

In case of Constructors, When you update fields, you create a new object every time by using newkeyword.

对于构造函数,当您更新字段时,每次都使用new关键字创建一个新对象。

Customer customer = new Customer("Tom", 23, 10000);

For example, if you want to update the salary of Tom, you need to write this line again with updated salary, that means memory is wasted.

例如,如果要更新 Tom 的工资,则需要将更新后的工资再次写入这一行,这意味着浪费了内存。

In case of setter methods you can set individual fields in original object only.

在 setter 方法的情况下,您只能在原始对象中设置单个字段。

回答by S. Mayol

I think you asked a good question: - But when do we use constructors and when do we use setters?

我认为你问了一个很好的问题: - 但是我们什么时候使用构造函数,什么时候使用 setter?

First, let's start with some concepts. I hope this explanation helps everybody that want to know when to use constructors or setters() and getters() methods (Accessors and Mutators). Constructorsare similar to Methods, however there are few differences between constructorand methodin java:

首先,让我们从一些概念开始。我希望这个解释能帮助每个想知道什么时候使用构造函数或 setters() 和 getters() 方法(访问器和修改器)的人。构造函数类似于方法,但是在java中构造函数方法之间几乎没有区别:

1) Constructoris used to initialize the state of an object. Methodis used to expose behaviour of an object.

1)构造函数用于初始化对象的状态。 方法用于公开对象的行为。

2) Constructormust not have return type. Methodmust have return type.

2)构造函数不能有返回类型。方法必须有返回类型。

3) Constructoris invoked implicitly. Methodis invoked explicitly.

3)构造函数被隐式调用。方法被显式调用。

4) Getters(), or accessors, are methods that provide access to an object's instance variables. Setters(), or mutators, are methods that provide the caller with an opportunity to update the value of a particular instance variable.

4) Getters()或访问器是提供对对象实例变量的访问的方法。Setters()或 mutators 是为调用者提供更新特定实例变量值的机会的方法。

Having this clear, let's think in term of Object Oriented Programming (OOP), to meet the requirement of OOP principals (The Objects Oriented Programming (OOP)is constructed over four major principles: Encapsulation, Data Abstraction, Polymorphismand Inheritance.), Getter()and Setter()methods is the key to achieve this.

清楚了这一点,让我们从面向对象编程(OOP)的角度来思考,以满足 OOP 原则的要求(面向对象编程(OOP)是通过四大原则构建的:封装数据抽象多态继承。),Getter ()Setter()方法是实现这一点的关键。

Here is a formula that is going to show you what I mean:

这是一个公式,它将向您展示我的意思:

Private fields + Public accessors == Encapsulation;

私有字段 + 公共访问器 == 封装;

As you can see based on this formula when we set private fields and use public accesors we are performing encapsulation one of the 4 OOP principals.

正如您在设置私有字段并使用公共访问器时基于此公式所看到的,我们正在执行 4 个 OOP 主体之一的封装。

Here I am going to provide you two classes, I added comment on it to try to make my code self explaining. Take these classes as a lab on methods with Customerand TestCustomer[the one with the main()method] classes, you can copy the code and run it yourself. Note I used two constructors in order to explain a class having multiple constructors and having public setters()and getters()methods in order to access private instance variables:

在这里,我将为您提供两个类,我添加了注释以尝试使我的代码自我解释。将这些类作为带有方法的实验室CustomerTestCustomer[带有main()方法的类] 类,您可以复制代码并自己运行它。注意我使用了两个构造函数来解释一个具有多个构造函数并具有公共setters()getters()方法以访问私有实例变量的类:

package com.exercise.lecture2;

/**
 * 1) Create a Customer class that has the following attributes:
 * name, SSN.
 * 2) This class should have two methods: getName() and getSSN().
 * 3) If the class is instantiated with only a SSN, then give the default name of "John Doe". (HINT: Use two constructors)
 * 4) Also, add a method toString(), that returns a string representation of the customer object (name and SSN concatenated).
 *      Make sure to set this method public.
 * 5) Create a class to test your program (e.g. a class that include the main() method). In your test program, instantiate
 *      three customers and print out the value using toString() method.
 * 
 * @author Samuel M.
 *
 */

//this class is complemented with class  TestLabCustomer.java
public class LabCustomer {

// Private filds: name and socialSecurityNum
    private String name;
    private int socialSecurityNum;

    // constructors
    public LabCustomer(String name, int socialSecurityNum) {
        this.name = name;
        this.socialSecurityNum = socialSecurityNum;
    }

    /** The keyword 'this' can be used to call a constructor from a constructor,
     * when writing several constructor for a class, there are times when
     * you'd like to call one constructor from another to avoid duplicate code.
     */
    // Account with This() on a second constructor
    public LabCustomer(int socialSecurityNum) {
        this("John Doe", socialSecurityNum); // default name is printed if only the SSN is provided
    }

    // Public accessors (getters and setters)
    String getName() {
        return name;
    }

    void setName(String name) {
        this.name = name;
    }

    int getSSN() {
        return socialSecurityNum;
    }

    void setSSN(int socialSecurityNum) {
        this.socialSecurityNum = socialSecurityNum;
    }


    // instance method
    public String toString() { //overriding the toString() method 
        return ("Customer name: " + getName() + ", SSN#: " + getSSN() ); // concatenating the name and SSN

    }
}

Here is the test class, the one that has the main()method and calling an instance method after instantiating an object of the previews class:

这是测试类,该类具有main()方法并在实例化预览类的对象后调用实例方法:

package com.exercise.lecture2;

//this class is complemented with class  LabCustomer.java
public class TestLabCustomer {

    public static void main(String[] args) {
        // Instantiating an object of class LabCustomer and creating three customers objects
        LabCustomer cust1 = new LabCustomer("Juan Melendez", 123457789);
        LabCustomer cust2 = new LabCustomer("Mary Lee", 125997536);
        LabCustomer cust3 = new LabCustomer(124963574); // when instantiating with no "name", the default (John Doe) is printed 

        /**
         * Once you've instantiated an object and have an object variable,
         * you can use object variable to call an instance method. 
         *  e.g.:
         *  object variables: cust1, cust2, cust3
         *  call the method toString() using the object variable and dot [.] in order to perform the method call.
         */
        // calling method toString() in class LabCustomer to print customer values
        System.out.println(cust1.toString());
        System.out.println(cust2.toString());
        System.out.println(cust3.toString());

    }

}

result:

Customer name: Juan Melendez, SSN#: 123457789

Customer name: Mary Lee, SSN#: 125997536

Customer name: John Doe, SSN#: 124963574

结果:

客户名称:Juan Melendez,SSN#:123457789

客户名称:Mary Lee,SSN#:125997536

客户名称:John Doe,SSN#:124963574

回答by Ravindra babu

In simple terms:

简单来说:

Use constructorif you think initialization is mandatory before you can use the object.

如果您认为在使用对象之前必须进行初始化,请使用构造函数。

Use settermethod when initialization of variable is non-mandatory to use the object.

当变量的初始化不是必须使用对象时,请使用setter方法。

Refer to documentation pagefor more details.

有关更多详细信息,请参阅文档页面