我有 2 个类(class):日期和人员
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
的私有(private)内部类
现在上面的构造函数代码不再起作用了。 这是错误消息:
Description Resource Path Location Type No enclosing instance of type Person is available due to some intermediate constructor invocation Person.java /Wk03_Ch10_FileIO_Ch13_Interfaces/wk03_Ch10_FileIO_Ch13_Inner_Classes line 43 Java Problem`
如何解决这个问题?我可以这样做:
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()
方法的要求。
最佳答案
您无法在调用另一个构造函数时创建内部成员(非静态
)类。来自 JLS §8.8.7.1 :
An explicit constructor invocation statement in a constructor body (sic: the call to
this()
) may not refer to any instance variables or instance methods or inner classes declared in this class or any superclass, or usethis
orsuper
in any expression; otherwise, a compile-time error occurs.
原因是非静态
内部类可能需要在构造类时访问该类。例如:
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
内部类时,它可以从其封闭实例(OuterClass
,但封闭的 OuterClass
尚未调用 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
一旦声明为 static
,就无法从 OuterClass
访问 name
,因此我们必须显式传递它现在正在构建中,但这更好,因为无论如何初始代码都会被破坏。
编辑:
根据您的问题:
What confused me is that I can create an object of a
Date
type in thePerson
's constructor, as long as it is not inside thethis()
method. I can do this:Date dt = new Date(birthMonth, birthDay, birthYear);
What is the difference between the above andthis(...., new Date(birthMonth, birthDay, birthYear), ...)
?
不同之处在于,在 this()
之外的调用中,所有对 super()
的调用都已发生,它们作为 的一部分发生this()
因为隐式调用了 super()
,因此该对象已达到可以访问的程度。您的 Date
实例无法访问 Person
类,因为 Person
及其字段还没有上下文,因此编译器不会允许它。
简而言之,一旦调用了 this()
,那么至少会发生对 super()
的调用,这是此约束背后的驱动力,并且也是为什么不鼓励可重写方法调用的原因。如果某个方法被子类重写,然后在父类(super class)的构造函数中调用,则在子类初始化之前就可以访问子类中的字段,甚至会导致 final 返回
字段。 基本上,这都是为了在调用 null
super()
之前保护自己不访问您的类。
关于java - 内部类和 this() 构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17017838/