在子类中使用“this”/“super”都会给出超类的字段,但在子类构造函数中只允许使用“super” [duplicate]

Using "this"/"super" in the subclass both give superclass's fields but only "super" is allowed in subclass constructor [duplicate]

提问人:constantem 提问时间:12/21/2021 更新时间:12/21/2021 访问量:398

问:

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

超级类:

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

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

subclass 方法中使用的 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;
    }
...
}
Java 构造函数 This Super

评论

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

答:

1赞 f.trajkovski 12/21/2021 #1

使用 -> 时,您可以指向当前对象,更准确地说,指向将从当前类创建的对象。在这种情况下,您可以使用父类访问字段。更准确地说,是您可以访问该参数,因为它是在(父类)中定义的,但所有要定义的字段都应指向 .另请注意,在您必须调用的构造函数中,因为您定义了构造函数,说这些字段将在创建对象时设置,并且再次为它们提供值。thissuperAnimalsuperageAnimalDogthisDogsuperAnimalDog

2赞 001 12/21/2021 #2

在 和 中是不需要的。仅当子类声明的成员变量与超类同名时,才需要它们: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
1赞 rzwitserloot 12/21/2021 #3

this,关键字有两个单独的作业。

这就像 java 中两个完全不同的东西:做整数加法,做字符串连接。相同的符号,2 个不相关的工作。在英语中,银行这个词既意味着河边的土地,也意味着金融机构。同一个词,2个不相关的工作。+5 + 2"foo" + "bar"

this也不例外。

  1. 它的意思是“这个对象”。这里只有一个对象:Dog 类型的对象。没有“狗对象”,里面包含一个单独的“动物超级对象”。但事实并非如此。只有 Dog 对象,它包含所有字段 - 您在 Dog 中定义的任何字段,以及您在 Animal 中定义的任何字段。

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

  1. 这也意味着:选择一个构造函数。此版本的关键字始终在关键字后面紧跟括号。 是它的外观,它允许您从另一个构造函数调用其中一个构造函数。 是一个类似的构造,可让您调用超级构造函数之一。请注意,所有构造函数都必须使用其中之一;如果不这样做,编译器将作为第一行静默注入到构造函数中。thisthis(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;
}

这里的第一个用法很简单:使用提供的值调用其他构造函数。第二种(以及第三种和第四种)用法是“it is this object”变体。

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

相反,表示“将此对象字段的值设置为参数的值”。this.name = name;namename

评论

0赞 constantem 12/21/2021
谢谢rzwitserloot,非常清楚!