我的 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 语法强制调用另一个构造函数(在 this
或 super
类中)作为任何构造函数中的第一个语句。请参阅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/