我有两个课程:日期和人员 Person有两个Date类
属性案例1
Date
类是Person类的独立类。我让这段代码正常工作:
private String name;
private Date born;
private Date died; // null indicates still alive.
public Person(String initialName, int birthMonth, int birthDay,
int birthYear) {
// requirement from the instructor:
// **implement using the this() constructor**
this(initialName, new Date(birthMonth, birthDay, birthYear), null);
}
案例2:内部类(作业要求)
我将Date
作为Person
现在上面的构造函数代码不再起作用了。 以下是错误消息:
描述资源路径位置类型 由于某些中间构造函数调用Person.java / Wk03_Ch10_FileIO_Ch13_Interfaces / wk03_Ch10_FileIO_Ch13_Inner_Classes第43行Java问题`没有封闭的Person类型实例
我该如何解决这个问题?我可以这样做:
Date dt = new Date(birthMonth, birthDay, birthYear);
不幸的是this()
必须是构造函数中的第一行
另一种解决方法是
public Person(String initialName, int birthMonth, int birthDay,
int birthYear) {
// implement using the this() constructor
this.name = initialName;
this.born = new Date(birthMonth, birthDay, birthYear);
this.died = null;
}
然而,最后一段代码不满足我的教师在构造函数中使用this()
方法的要求。
答案 0 :(得分:2)
您无法在对另一个构造函数的调用中创建内部成员(非static
)类。来自JLS §8.8.7.1:
构造函数体中的显式构造函数调用语句(sic:对
this()
的调用)可能不会引用任何实例变量或实例方法或< strong>在此类或任何超类中声明的内部类,或在任何表达式中使用this
或super
;否则,发生编译时错误。
原因是非static
内部类可能需要在构造时访问该类。例如:
public class OuterClass {
private String name;
private InnerClass inner;
public OuterClass(String name, InnerClass inner) {
this.name = name;
this.inner = inner;
}
public OuterClass(String name) {
this(name, new InnerClass()); // Will not compile
}
public class InnerClass {
public InnerClass() {
// Access to name is allowed since this inner class isn't static
System.out.println(name);
}
}
}
这里的主要问题是,当我们构造非static
内部类时,它可以从其封闭的实例(static
访问非OuterClass
成员,但是封闭的OuterClass
{1}}尚未调用super()
,因此被认为是不安全的。事实上,如果允许编译该代码,由于构造函数调用顺序,它将打印null
。简而言之,InnerClass
会在调用this.name = name
之前创建,这与this question中提供的信息类似。
解决方法是让InnerClass
成为static
内部类并直接将名称传递给它:
public class OuterClass {
private String name;
private InnerClass inner;
public OuterClass(String name, InnerClass inner) {
this.name = name;
this.inner = inner;
}
public OuterClass(String name) {
this(name, new InnerClass(name));
}
public static class InnerClass {
public InnerClass(String name) {
System.out.println(name);
}
}
}
一旦声明InnerClass
, name
无法从OuterClass
访问static
,因此我们现在必须在构建时明确传递它,但这是因为初始代码更好无论如何都会被打破。
修改强>
根据你的问题:
让我感到困惑的是,我可以在
Date
的构造函数中创建Person
类型的对象,只要它不在this()
方法中。我可以这样做:Date dt = new Date(birthMonth, birthDay, birthYear);
上述内容与this(...., new Date(birthMonth, birthDay, birthYear), ...)
之间有什么区别?
不同之处在于,在this()
之外的通话中,所有对super()
的调用都已发生,它们作为this()
的一部分发生,因为对{{1}的隐式调用因此,对象已达到可以被访问的点。您的super()
实例无法访问Date
类,因为Person
及其字段尚无上下文,因此编译器不允许它。
简而言之,一旦Person
被调用,那么至少调用了this()
,这是此约束背后的驱动力,也是为什么不鼓励可覆盖方法调用的原因。如果一个方法被一个子类覆盖,然后在超类的构造函数中调用,则可以在子类甚至初始化之前访问子类中的字段,甚至导致super()
字段返回null
。 基本上,所有这些都是为了在调用final
之前保护自己无法访问您的课程。
答案 1 :(得分:0)
虽然我永远不会在Date
类中创建Person
类(从应用程序建模的角度来看,这听起来不错!),您似乎已经说过这是一个必需一些任务。
如果你这样设置:
public class Person {
...
class Date {
...
}
}
然后在Person
的内部方法中,您需要使用以下命令调用Date
构造函数:
this.new Date(...)
这是Java使用的语法。您需要一个类型为Person的封闭实例来创建内部类的对象。关于内部类(无论它们是成员,本地还是匿名)的事情是每个实例都存在绑定到外部类的实例。所以如果我有个人实例p
,我可以说:
p.new Date(...)
这里的一个大问题是你无法在使用即将创建的人的Person
构造函数中创建日期!例如,fails:
public Person() {
this(this.new Date());
}
因为this
的值尚未准备好以这种方式使用(尽管有趣的是,在其他情况下,有时可以在构造函数中使用this
,例如将其存储在数组中,例如)。
就像你意识到的那样,使Date
成为一个静态嵌套类是好的,因为静态嵌套类的实例并没有绑定到封闭类的任何实例,所以这是最好的解决方案。如果你真的必须拥有一个内部类,那么你将无法将新日期作为this()
表达式的“参数”传递,并将其绑定到您正在创建的人身上!也许这就是作业的重点(这是一个研究生班吗?: - ))