Java 课堂最佳实践
如果我有一个带有重载构造函数的customer类(默认值和带参数的),那么在重载构造函数中设置类成员的正确方法是什么?使用“this”引用还是使用setter方法 只是不确定正确的方法是什么Java 课堂最佳实践,java,Java,如果我有一个带有重载构造函数的customer类(默认值和带参数的),那么在重载构造函数中设置类成员的正确方法是什么?使用“this”引用还是使用setter方法 只是不确定正确的方法是什么 public class Customer { private String firstName; private String lastName; private int age; public Customer() {} //This Way public Customer(String firs
public class Customer {
private String firstName;
private String lastName;
private int age;
public Customer() {}
//This Way
public Customer(String firstName, String lastName, int age)
{
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
// Or this way?
public Customer(String firstName, String lastName, int age)
{
setFirstName(firstName);
setLastName(lastName);
setAge(age);
}
/**
* @return the firstName
*/
public String getFirstName() {
return firstName;
}
/**
* @param firstName the firstName to set
*/
public void setFirstName(String firstName) {
this.firstName = firstName;
}
/**
* @return the lastName
*/
public String getLastName() {
return lastName;
}
/**
* @param lastName the lastName to set
*/
public void setLastName(String lastName) {
this.lastName = lastName;
}
/**
* @return the age
*/
public int getAge() {
return age;
}
/**
* @param age the age to set
*/
public void setAge(int age) {
this.age = age;
}
}基本上,除了验证,没有区别 一方面,如果setter仅基于新值验证新值(它们不依赖于对象状态),则调用setter可避免重复验证逻辑 另一方面,如果一个setter的验证检查了其他属性,那么在调用该setter之前,您必须确保已经设置了所需的属性,或者直接分配属性。第一个属性(使用
this.
)可能更安全、更直接。考虑将来的子类是否超过了SETTER方法——这可能会导致非常意外的行为。
如果你的类是final,这是不相关的,这是一个清洗。直接访问方式更快(如果内存正常,速度会快7倍),但第二种方式“更安全”,以防有一些特殊规则来分配这些值或分配链(从另一个字段的setter中分配第二个字段)在访问器中实现的地方,这当然是除非您希望在从构造函数完成赋值时明确绕过这些规则/链接
总之,这取决于你的需要,但这些是我能想到的主要问题。最好的答案是“取决于”。通常,您不需要使用setter,除非setter在设置值之前执行更类似于计算的操作。但是,如果您的设置器仅直接设置值,则
此
可能最适合您。相反,setter用于验证和其他用途,如果你使用this
,你会错过它们。这不是关于哪种方法更好,而是你想从中得到什么
-如果您希望类是可更改的,那么使用setters
-如果您希望类是不可变的
,那么我认为使用这个
是一个更好的选择
我认为使用这个
,适用于以下情况:您从Web服务器或某个源接收一些数据,然后将它们以自定义类实例的形式存储到集合中
例如:
- 创建一个班级学生
- 当您向某个web服务发出请求时,您将得到响应,例如:
JSON
- 解析它,然后创建Student的实例并将其存储在集合中
例如:
ArrayList arList=new ArrayList()代码>
arList.add(新学生(姓名、学号、班级、分数))代码>
这是迄今为止唯一合理的答案。事实上,由于这个问题,一些lint工具会警告从构造函数调用非final方法。(如果类不是final,但setter方法是final,那也一样好。)@KumarVivekMitra-我不喜欢你的答案,正如我对它的评论所表明的那样。@TedHopp请再次阅读我的答案……我想我们谈论的是同一件事。。。。。还是让我在这里再写一遍吧……我想你们是在学习
OCP
原理,,,类是开放的,可以扩展,但可以修改。。。。正如我所知,构造函数不能被继承,也不能被重写,所以它是不可变的……
@KumarVivekMitra-如果一个类有一个setter,那么它是可变的(或者setter做什么)。据我所知,“可变”和“不可变”这两个术语不适用于构造函数。@TedHopp我不是说构造函数是不可变的,我是说Clas是不可变的。。。。。在我的回答中写得非常清楚……第二种方法远远不是“更安全的”,除非setter方法(或类)是final
。如果一个子类重写setter而无法调用超类,该怎么办?如果你正在对一个类型进行子类化,并且重写setter方法而没有对其进行任何设置,那么你将遇到比决定使用哪个构造函数更大的问题。@TedHopp我正在写一篇关于Jordan White所说内容的详细描述,所以我就不谈了:)@JordanWhite-我想你误解了这个问题。这里不涉及“基本类”问题。正在设置的变量是类的私有变量。OP使用了“base”,其中“default”更合适。@TedHopp我对这个问题读得很好,无法想象有人继承一个类只是为了重写setter方法而不更新超类。从构造函数调用非final方法(如setter)不是一个好主意。请看,例如,@TedHopp我想您正在学习关于OCP
原则,,,类是开放的,可以扩展,但是关闭了,可以修改。。。。正如我所知,构造函数不能被继承,因此不能被重写,因此它是不可变的……
请参阅,以获得有关为什么永远不应从构造函数调用可重写方法的良好解释。大多数lint工具都会抱怨从构造函数调用setter方法(除非方法或类是final的,或者方法是私有的——在