java - 内部类和 this() 构造函数

标签 java constructor this inner-classes

我有 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 use this or super 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 the Person's constructor, as long as it is not inside the this() method. I can do this: Date dt = new Date(birthMonth, birthDay, birthYear); What is the difference between the above and this(...., 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/

相关文章:

javascript - 为什么我应该在 Person Constructor(和类似的构造函数)中使用 `this.name` 而不是 `name`?

java - 是否有与嵌套类关联的构造函数

php - PHP 类或 PHP 方法中的 self 和 $this-> 之间的区别在哪里?

java - JButton 被删除后会在 JPanel 中留下痕迹吗?

c++ - 用友元类重载构造函数

java - 引用封闭对象通过匿名类转义-java

java - 请向我解释 "this"

java - 如何将BST的所有数据存储到一个数组列表中?

java - 如何从可能返回 null 的方法中分配变量?

java - SpringMVC @Scope session 不创建线程