java - 为什么我在构造函数中执行某些操作后无法调用 "this"

标签 java constructor this

我的 Date 类有 2 个构造函数。第一个只有 3 个 int 参数,分别代表月、日和年。第二个,我提供它,以防用户将字符串作为一个参数来表示月/日/年。

由于软件规则#1:不要重复代码。我决定在第二个构造函数中解析字符串,并使用第一个构造函数来验证日期是否有效。所以最后我调用它来提供与第一个构造函数相同的 3 int 参数。

嗯,编译器给了我这个错误: 错误:对此的调用必须是构造函数中的第一个语句。

我知道我可以通过这种方式获得第二个构造函数,但这违反了软件规则#1。

  public Date(String s) {
    String[] strSplit = s.split("/");
    month = Integer.parseInt(strSplit[0]);
    day = Integer.parseInt(strSplit[1]);
    year = Integer.parseInt(strSplit[2]);
    if (isValidDate(month, day, year)) {
      this.month = month;
      this.day = day;
      this.year = year;
    } else {
      System.out.println("Fatal error:  Invalid data.");
      System.exit(0);
    }
  }

请看一下第一个和第二个构造函数:

class Date {

  private int month;
  private int day;
  private int year;

  public Date(int month, int day, int year) {
    if (isValidDate(month, day, year)) {
      this.month = month;
      this.day = day;
      this.year = year;
    } else {
      System.out.println("Fatal error:  Invalid data.");
      System.exit(0);
    }
  }

  public Date(String s) {
    String[] strSplit = s.split("/");
    int m = Integer.parseInt(strSplit[0]);
    int d = Integer.parseInt(strSplit[1]);
    int y = Integer.parseInt(strSplit[2]);
    this(m, d, y);
  }
  .
  .
  .
  public static void main(String[] argv) {
    Date d1 = new Date(1, 1, 1);
    System.out.println("Date should be 1/1/1: " + d1);
    d1 = new Date("2/4/2");
    System.out.println("Date should be 2/4/2: " + d1);
  }
}

最佳答案

正如评论中提到的,Java 语法强制调用另一个构造函数(在 thissuper 类中)作为任何构造函数中的第一个语句。请参阅JLS §8.8.7. Constructor Body欲了解更多信息:

The first statement of a constructor body may be an explicit invocation of another constructor of the same class or of the direct superclass (§8.8.7.1).

但是让我向您展示一种创建类的合理方法。大多数情况下,您的需求可以通过工厂方法来解决:

    public final class Date {
        final int year;
        final int month;
        final int day;

        public static Date parse(String dateAsString) {
            String[] strSplit = dateAsString.split("/");
            int m = Integer.parseInt(strSplit[0]);
            int d = Integer.parseInt(strSplit[1]);
            int y = Integer.parseInt(strSplit[2]);
            return new Date(y, m, d);
        }

        public Date(int year, int month, int day) {
            checkValues(year, month, day);
            this.year = year;
            this.month = month;
            this.day = day;
        }

        private static void checkValues(int year, int month, int day) {
            if (!isValidDate(year, month, day))
                throw new IllegalArgumentException("Invalid date values.");
        }

        private static boolean isValidDate(int year, int month, int day) {
            // TODO Validation!
            return true;
        }
    }

应用 DRY principle构造函数主要是通过构造函数链接完成的。想象一下,您还必须为只有年份或只有年份和月份的日期创建构造函数。提供两个新的构造函数:

public Date(int year) { this(year, 1, 1); }
public Date(int year, int month) { this(year, month, 1); }

请注意,这不是表示仅年份日期的最佳方式。也许您可以允许值为 0。例如,它会变成 this(year, 0, 0)

关于java - 为什么我在构造函数中执行某些操作后无法调用 "this",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45296613/

相关文章:

带有 google map 的 Java 桌面应用程序

java - Android Libgdx 致命信号 11(SIGSEGV),代码 1,故障地址 0x0

c++ - 如何创建一个只能被自己类调用的构造函数?

Javascript underscore.js-我必须使用上下文参数和 'this' 吗?

JavaScript : Onload with reference to class property

javascript - 粘贴事件中的 typescript 回调为空

java - 在类之间传递变量时出现 NullPointerException

java - 计算范围内的素数 RMI 版本与并发版本

java - 类构造函数对象无法正确显示

c++ - 在 C++ 中不调用构造函数