到目前为止,我已经看到了两种在Java中设置变量值的方法。有时使用带参数的构造函数,其他setter方法用于设置每个变量的值。
我知道一旦使用“new”关键字实例化一个类,构造函数就会在类中初始化一个实例变量。
但是我们什么时候使用构造函数?何时使用setter?
答案 0 :(得分:40)
当您想要创建对象的新实例时,您应该使用构造函数方法,并且已填充值(已填充值的可立即使用的对象)。这样,您无需为对象中的每个字段显式调用setter方法来填充它们。
如果要在创建对象后更改字段的值,请使用setter方法设置值。
例如: -
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 :(
正如Axel所提到的,如果你想创建不可变对象,你就不能使用setter-methods方法。我不会说必须在构造函数中初始化所有内容,因为存在不同的方法,例如懒惰评估,甚至可以使用不可变对象。
答案 1 :(得分:6)
我想你提出了一个很好的问题: - 但我们什么时候使用构造函数?何时使用setter?
首先,让我们从一些概念开始。我希望这个解释可以帮助每个想知道何时使用构造函数或setter()和getters()方法(Accessors和Mutators)的人。 构造函数与方法类似,但 构造函数 与 方法<之间的差异很小java中的/ em> :
1) 构造函数 用于初始化对象的状态。 方法 用于公开对象的行为。
2) 构造函数 不得包含返回类型。 方法 必须具有返回类型。
3)隐式调用 构造函数 。 方法 是明确调用的。
4) Getters() 或访问器是提供对象实例变量访问的方法。 Setters() 或mutators是为调用者提供更新特定实例变量值的机会的方法。
明确这一点,让我们考虑面向对象编程(OOP),以满足OOP主体的要求(面向对象编程(OOP)是在四大原则: 封装 , 数据抽象 , 多态性< / em> 和 继承 。), Getter()和 Setter()方法是实现这一目标的关键。
这是一个能告诉你我的意思的公式:
私人字段+公共访问者==封装;
正如您在设置私有字段和使用公共加密器时基于此公式所看到的,我们正在执行4个OOP主体之一的封装。
在这里,我将为您提供两个课程,我添加了评论,试图让我的代码自我解释。将这些类作为实验室,使用Customer
和TestCustomer
[具有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
}
}
这是测试类,它具有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());
}
}
结果:
客户名称:Juan Melendez,SSN#:123457789
客户名称:Mary Lee,SSN#:125997536
客户名称:John Doe,SSN#:124963574
答案 2 :(得分:4)
如果你想拥有一个不可变的类使用构造函数,否则使用setter。
答案 3 :(得分:3)
答案 4 :(得分:2)
假设我们有一个名为Counter的课程:
public class Counter{
int count;
//constructor
public Counter(int c){
count = c;
}
public void setCounter(int newCounter){
count = newCounter;
}
}
在上面的类中,当您想要创建 new Counter对象时,您将使用构造函数并在其中设置count变量。像这样:
Counter myCounter = new Counter(1);
如果要在运行时期间更改计数变量,可以使用setter方法:
myCounter.setCounter(2);
答案 5 :(得分:1)
在大多数情况下,我同时使用它们:)(因为你有9/10次想要回来并编辑一些东西(并且这不是一个很好的实例来制作它的新实例)
我通常会做类似的事情
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
}
当你想用它编辑一些东西时你可以使用setter,(例如,如果你将用户保存在ArrayList中,那么你可以从arraylist中获取对象并设置字段)你想编辑,而不是制作一个全新的对象:)
答案 6 :(得分:1)
我们根据场景使用该方法。
如果我们在实例化类的对象时有一组值,那么那时我们将使用构造函数方法。
当我们在创建对象实例时不知道值集时,我们将使用setter方法。
答案 7 :(得分:1)
这取决于应用程序域和类中的目的。
Java bean通常没有arg构造函数和相关成员变量的getter / setter。这种方法有一些优点,因为许多框架(如Struts和Spring)都支持Java bean。
类还可以通过将这些变量作为参数传递给基础构造函数来强制实施值的强制可用性。并且可以通过其他便捷构造函数或setter方法设置非强制值。
另一方面,不可变类可以有构造函数,但需要缺省方法来修改其状态,包括setter。
总的来说,这样的决定可以考虑到应用程序的整体设计,运行的框架 1 ,必须强制执行的合同等等。
1 - 虽然,它建议类设计应该独立于框架。像Spring这样的好框架不会强制执行这些要求。
答案 8 :(得分:1)
如果是构造函数,当您更新字段时,每次都使用 new 关键字创建一个新对象。
Customer customer = new Customer("Tom", 23, 10000);
例如,如果你想更新Tom的工资,你需要用更新的工资再次写这一行,这意味着浪费了内存。
如果是setter方法,您只能在原始对象中设置单个字段。
答案 9 :(得分:0)
您可以将这两种方法结合起来。在构造函数中,您可以调用实例变量的setter。类似的东西:
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;
}
}