Java - 来自构造函数的setter

时间:2012-09-21 15:09:11

标签: java constructor setter

package cen.col.course.demo;

import java.io.Serializable;

public class Course implements Serializable {

private static final long serialVersionUID = 1L;
protected String code;
protected String title;
protected Professor professor;

public Course( String code) throws InvalidDataException {
    super();
    setCode(code);
}

public Course(String code, String title ) throws InvalidDataException  {
    this(code);
    setTitle(title);
}

public Course(String code, String title, Professor professor) throws InvalidDataException   {
    this(code,title);
    setProfessor(professor);
}
    public String getCode() {
    return code;
    }

protected void setCode(String code) throws InvalidDataException {
    if ( code == null || code.length() < 1) {
        throw new InvalidDataException("Course must have a course code");
    }
    this.code = code;
}

public String getTitle() {
    return title;
}

public void setTitle(String title)  throws InvalidDataException {
    if ( title == null || title.length() < 1) {
        throw new InvalidDataException("Course must have a title");
    }
    this.title = title;
}

public Professor getProfessor() {
    return professor;
}

public void setProfessor(Professor professor) {
    this.professor = professor;
}

public String toString() {
    String output = getCode() + ": [" + getTitle() + "]";
    if (getProfessor() != null ) {
        output += " is taught by " + getProfessor();
    }
    return output;
}

public boolean equals(Course c) {
    if ( ! this.getCode().equals(c.getCode())){
        return false;
    }
    if ( ! this.getTitle().equals(c.getTitle())){
        return false;
    } 
    // should the prof field be included in test for equality?
    if ( ! this.getProfessor().equals(c.getProfessor())){
        return false;
    } 
    return true;
}


}

我有三个问题:

  1. 我注意到我的教授从构造函数中调用了setter方法。我做了一些搜索,并对它有不同的想法。有人说没关系,有人说你在使用子类时要小心,是否可以从构造函数中调用你的setter?

  2. 构造函数抛出异常,因为她从构造函数中调用setter。现在我的问题是,如果从构造函数中调用setter并不是一种安全的方法,那么这样做的正确方法是什么?我的猜测是声明一个无参数构造函数,并使用setter构建对象。

  3. 我想这样做是不可能的?

    课程createCourse =新课程(“1234”,“编程1”,“Pam Halpert”);

  4. 我正在调用带有3个参数的构造函数,但是,如果从构造函数中调用setter是不安全的,那么如何执行此操作并具有异常?我可以使用if语句吗?检查是否有空白并在必要时抛出异常?

4 个答案:

答案 0 :(得分:1)

  1. 在构造函数中调用setter通常具有以下优点:有时setter内部已经有一些验证逻辑(比如示例中的setTitle),并且您不希望复制此逻辑。但是,正如您已经提到的,调用setter可能会导致问题,即子类可能会以意外行为覆盖它们。要解决此问题,您可以将setter设置为private或final,以便它们不会被覆盖。只调用私人/最终制定者是一种很好的做法,不应该导致任何问题。

  2. 获取无效数据的构造函数抛出异常是很好的。您不想创建无效对象。

  3. 首先创建一个空对象(通过空构造函数)然后通过setter填充其数据是一种不太好的做法。通过这种方式,您将有一段时间处于无意义状态的对象,该对象具有一些数据填充,一些数据未填充,这可能会导致麻烦。另外,正如另一个已经提到的答案,您应该考虑减少构造函数的数量 - 没有教授的课程真的有效吗?如果不是,则不需要是构造者创建这样的对象......

答案 1 :(得分:0)

就我个人而言,我不是一个狂热的粉丝。我喜欢不变性,所以在你的例子中我会将参数传递给ctor。在那里检查,然后分配到最终字段。塞特斯不存在。你只会有吸气剂。

如果要更新,则可以引入复制构造函数。

然后你会知道构造它的对象处于有效状态。如果它的某些部分为null,那么您可以重载构造函数。你不知道需要通过no-arg constrcturs和setter来填充哪些字段。通过在构造函数中使用参数强制执行它,您将强制将对象初始化为有效状态。

答案 2 :(得分:0)

如果您的setter执行某种形式的数据验证,则调用setter非常有用。这允许您将验证放在一个位置,并确保在实例化时设置的属性符合验证规则。

然而,问题是子类可能会覆盖这些setter,这意味着您的预期验证不再发生。

因此,创建执行验证的私有 setter是有意义的。在构造函数中调用这些私有的setter。如果您想拥有公共设置器,那很好,只需在您的私有设置器周围创建一个公共包装器设置器。


旁注:

你教授的例子有点不对劲。

验证似乎旨在确保始终设置titlecode。但是,代码还提供了允许您设置title的构造函数。这几乎肯定是一个错误(我肯定会在代码审查中将其标记为一个错误)。

答案 3 :(得分:-1)

由于这是家庭作业或一些学习,你的教授很想给你看东西。

然而,

Course createCourse = new Course("1234","Programming 1","Pam Halpert");

实际上是最好的事情。

根据您正在开发的内容,大多数情况下,您希望提供尽可能少的构造函数,除非您正在设计编程语言。如果您正在使用公共API或产品,那么您应该确保您的消费者不会犯错误或滥用您的API,如果您允许他们创建错误。

构造函数可以抛出异常,这很好。

据我所知,调用setter的原因是做了一些验证或一些逻辑。这很好。

请记住,在构造函数中进行任何工作都被认为是一种不好的做法。

你应该在类之外完成它并将它们作为构造函数参数或setter / getter传递。