【问题标题】:Using "this"/"super" in the subclass both give superclass's fields but only "super" is allowed in subclass constructor [duplicate]在子类中使用“this”/“super”都给出了超类的字段,但在子类构造函数中只允许使用“super”[重复]
【发布时间】:2022-01-22 22:27:15
【问题描述】:

我正在尝试了解 this 和 super 在子类方法和子类构造函数中的用法:

超类:

public class Animal {
    protected String name;
    protected String age;

    public Animal(String name, String age) {
        this.name = name;
        this.age = age;
    }
}

子类方法中使用的this和super关键字:

public class Dog extends Animal {

    public Dog(String name, String age) {
        super(name, age);
    }

    public void display() {
        this.name = "Doggy";
        super.age = "20";
        System.out.println(this.name + " is " + super.age + " years old");
    }
}

上述案例中的“this”和“super”有什么区别?为什么在子类构造函数中我们不能使用"this"来初始化继承自超类的字段,如下例,但是我们可以使用super()来初始化超类中的相同字段?

public class Dog extends Animal {

    public Dog(String name, String age) {
        this.name = name;
        this.age = age;
    }
...
}

【问题讨论】:

  • FWIW,在您的“显示”方法中,您根本不需要 thissuper。它们在该上下文中的作用是明确指定您正在谈论的对象(并且那里只有一个对象,尽管它由两个类定义定义)。
  • "在上述情况下,"this" 和 "super" 有什么区别?" 在你的情况下没有区别,因为你没有用 在您的子类中具有相同的名称。 “为什么在子类构造函数中我们不能使用“this”来初始化从超类继承的字段”我们可以,但这不是问题。这里的问题是构造函数中的第一条指令需要调用一些super(..)。如果您希望编译器生成super(),则可以保留它,但由于您的超类没有无参数构造函数,您需要显式调用它。
  • Tldr,请“学习”docs.oracle.com/javase/specs/jls/se8/html/… (Ctrl+f, "this", "super")

标签: java constructor this super


【解决方案1】:

this -> 指向当前对象,更准确地说是从当前类创建的对象。使用super,您可以在本例Animal 中访问父类中的字段。更准确地说,是的,您可以使用super 访问age 参数,因为它是在Animal(父类)中定义的,但是将在Dog 中定义的所有字段都应该用this。另请注意,在Dog 的构造函数中,您必须调用super,因为您在Animal 中定义了构造函数,表示这些字段将在创建对象时设置,并且再次在Dog 中为它们赋值。

【讨论】:

    【解决方案2】:

    this,关键字,有两个独立的工作。

    这与+ 在java 中的含义完全相同:5 + 2 进行整数加法,"foo" + "bar" 进行字符串连接。相同的符号,2 个不相关的工作。在英语中,bank这个词既指河流旁边的土地,又指金融机构。同一个词,2 个不相关的工作。

    this 也不例外。

    1. 意思是“这个对象”。这里只有一个对象:Dog 类型的对象。没有“狗对象”,其中包含一个单独的“动物超级对象”。这不是它的工作原理。只有 Dog 对象,它包含所有字段 - 您在 Dog 中定义的任何字段,以及您在 Animal 中定义的任何字段。

    因此,this.someFieldDefinedInYourSuperClass = foo; 很好,这是有道理的。

    1. 这也意味着:选择一个构造函数。这个版本的this 关键字总是紧跟在关键字后面的括号中。 this(params); 就是它的样子,它允许您从另一个构造函数调用一个构造函数。 super() 是一个类似的构造,可让您调用您的超级构造函数之一。请注意,所有构造函数都必须使用其中之一;如果你没有这样做,编译器会静默地将super(); 作为构造函数的第一行注入。

    例子:

    public Student(LocalDate birthDate, String name) {
      this(generateNewStudentId(), birthDate, name);
    }
    
    public Student(String id, LocalDate birthDate, String name) {
      this.id = id;
      this.birthDate = birthDate;
      this.name = name;
    }
    

    这里的第一个用法很简单:使用提供的值调用另一个构造函数。第二个(以及第三个和第四个)用法是“它就是这个对象”变体。

    在您的示例中,您使用super(name, age);。这会从您的超类调用 public Animal(String name, int age) 构造函数。它没有“设置名称和年龄” - 它调用该构造函数。那个构造函数是做什么的?谁知道 - 你必须检查来源。也许构造函数首先从扬声器播放 Feliz Navidad。你碰巧知道它“只是”在this.name = name; this.age = age; 中起作用,但这只是因为那是Animal.java 中的当前内容。

    相比之下,this.name = name; 的意思是“将此对象的name 字段的值设置为name 参数的值”。

    【讨论】:

    • 感谢 rzwitserloot,非常清楚!
    【解决方案3】:

    display() 中,不需要this.super.。仅当子类声明与超类同名的成员变量时才需要它们:

    public static class Animal {
        protected String name;
        protected String age;
    
        public Animal(String name, String age) {
            this.name = name;
            this.age = age;
        }
    }
    public static class Dog extends Animal {
    
        protected String name;   // These are different from the ones
        protected String age;    // in Animal
    
        public Dog(String name, String age) {
            super(name, age);
            this.name = "Something else";
            this.age = "123";
        }
    
        public void display() {
            super.name = "Doggy";  // Need super. to differentiate from Dog class's name
            this.age = "20";
            System.out.println(this.name + " is " + this.age + " years old");
            System.out.println(super.name + " is " + super.age + " years old");
        }
    }
    
    public static void main (String[] args) throws java.lang.Exception
    {
        Dog dog = new Dog("Sparky", "3");
        dog.display();
    }
    

    输出是:

    Something else is 20 years old
    Doggy is 3 years old
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-24
      • 2015-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-04
      • 2014-02-17
      • 1970-01-01
      相关资源
      最近更新 更多