Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/86.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 课堂最佳实践_Java - Fatal编程技术网

Java 课堂最佳实践

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

如果我有一个带有重载构造函数的customer类(默认值和带参数的),那么在重载构造函数中设置类成员的正确方法是什么?使用“this”引用还是使用setter方法

只是不确定正确的方法是什么

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(新学生(姓名、学号、班级、分数))


正如前面所述,在构造函数中调用可重写方法是非常危险的。但是,如果您需要在setter中执行某种验证,您仍然有一些合理的方法来实现它

  • 让二传手进入决赛。最快的解决方案。这一点已经说过了,但它不是唯一的选择
  • 使用setter的私有副本
  • 使用工厂方法而不是构造函数。我通常坚持这个。因为这样,如果验证失败,您可以更自由地处理这种情况,并且它比(2)更好地传达意图

  • 这是迄今为止唯一合理的答案。事实上,由于这个问题,一些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的,或者方法是私有的——在