Java中“this”和“super”关键字之间的区别
关键字this
和super
什么区别?
两者都用于访问类权的构造函数? 你们能解释一下吗?
让我们考虑这种情况
class Animal { void eat() { System.out.println("animal : eat"); } } class Dog extends Animal { void eat() { System.out.println("dog : eat"); } void anotherEat() { super.eat(); } } public class Test { public static void main(String[] args) { Animal a = new Animal(); a.eat(); Dog d = new Dog(); d.eat(); d.anotherEat(); } }
输出将会是
animal : eat dog : eat animal : eat
第三行是打印“动物:吃”,因为我们叫super.eat()
。 如果我们调用this.eat()
,它会打印为“狗:吃”。
super
用于访问基类的方法,而用于访问当前类的方法。
扩展这个概念,如果你写了super()
,它指的是基类的构造函数,如果你写this()
,它指的是你正在编写这个代码的那个类的构造函数。
this
是对types化为当前类的对象的引用, super
是对作为其父类键入的对象的引用。
在构造函数中, this()
调用当前类中定义的构造函数。 super()
调用父类中定义的构造函数。 构造函数可以在任何父类中定义,但是它将引用与当前类最接近的覆盖。 以这种方式调用其他构造函数只能作为构造函数中的第一行。
调用方法的工作原理是一样的。 调用this.method()
将调用当前类中定义的方法,其中super.method()
将调用父类中定义的相同方法。
从你的问题来看,我认为你确实在构造函数链中使用this
和super
问题。 例如
public class A extends B { public A(...) { this(...); ... } }
与
public class A extends B { public A(...) { super(...); ... } }
区别很简单:
-
this
forms链接到当前类的构造函数中; 即在A
类中。 -
super
forms链接到直接超类中的构造函数; 即在B
class。
this
是指当前类的参考。
super
指的是当前类的父级(称为super
关键字)。
通过这样做,它允许您访问当前类的方法/属性(包括它自己的私有方法/属性)。
super
允许您访问父(基)类的公共/受保护的方法/属性。 您无法看到父级的私有方法/属性。
this
用于访问当前对象的方法和字段。 为此,例如,在静态方法中没有意义。
super
允许访问超类中的非私有方法和字段,并且只能从类的构造函数中访问构造函数。
编写代码时,你通常不想重复自己。 如果你有一个可以用不同数目的参数构造的类,一个避免重复你自己的常见的解决方法就是简单地调用另一个构造函数,在缺less的参数中使用默认值。 这只有一个恼人的限制 – 它必须是声明的构造函数的第一行。 例:
MyClass() { this(default1, default2); } MyClass(arg1, arg2) { validate arguments, etc... note that your validation logic is only written once now }
至于super()
构造函数,再次不像super.method()
访问它必须是你的构造函数的第一行。 之后,它非常像this()
构造函数,DRY(不要重复自己),如果你扩展的类有一个构造函数来完成你想要的东西然后使用它,然后继续构造你的对象,例如:
YourClass extends MyClass { YourClass(arg1, arg2, arg3) { super(arg1, arg2) // calls MyClass(arg1, arg2) validate and process arg3... } }
附加信息:
即使你没有看到它,默认的无参数构造函数总是先调用super()
。 例:
MyClass() { }
相当于
MyClass() { super(); }
我看到很多人提到在方法和variables上使用this
和super
关键字 – 都很好。 只要记住,构造函数对它们的用法有独特的限制,最值得注意的是它们必须是声明的构造函数的第一条指令,并且只能使用一个。
这个关键字用来调用同一个类中的构造函数(其他的重载构造函数)
语法 : this (args list); //与其他构造函数中的args列表兼容
super关键字用于调用超类中的构造函数。
语法: super(args list); //与超类的构造函数中的args列表兼容。
例如:
public class Rect { int x1, y1, x2, y2; public Rect(int x1, int y1, int x2, int y2) // 1st constructor { ....//code to build a rectangle } } public Rect () { // 2nd constructor this (0,0,width,height) // call 1st constructor (because it has **4 int args**), this is another way to build a rectangle } public class DrawableRect extends Rect { public DrawableRect (int a1, int b1, int a2, int b2) { super (a1,b1,a2,b2) // call super class constructor (Rect class) } }
1.使用SUPER关键字。
如果你的方法覆盖了它的一个超类的方法,你可以通过使用关键字super来调用被重写的方法。 你也可以使用super来引用一个隐藏的字段(虽然不鼓励隐藏字段)。 考虑这个类,超类:
public class Superclass { public void printMethod() { System.out.println("Printed in Superclass."); }
}
这里是一个名为Subclass的子类,它覆盖了printMethod():
public class Subclass extends Superclass { // overrides printMethod in Superclass public void printMethod() { super.printMethod(); System.out.println("Printed in Subclass"); } public static void main(String[] args) { Subclass s = new Subclass(); s.printMethod(); }
}
在Subclass中,简单名称printMethod()是指在Subclass中声明的一个,它覆盖了Superclass中的一个。 因此,要引用从Superclassinheritance的printMethod(),Subclass必须使用限定名称,如图所示使用super。 编译和执行子类打印以下内容:
超级印刷。 在子类中打印。
2.使用THIS关键字 与字段一起使用
使用this关键字的最常见原因是因为字段被方法或构造函数参数遮蔽。
例如,Point类就是这样写的
public class Point { public int x = 0; public int y = 0; //constructor public Point(int a, int b) { x = a; y = b; }
}
但它可能是这样写的:
public class Point { public int x = 0; public int y = 0; //constructor public Point(int x, int y) { this.x = x; this.y = y; }
}
构造函数的每个参数都会隐藏一个对象的字段 – 在构造函数中x是构造函数的第一个参数的本地副本。 要引用Point字段x,构造函数必须使用this.x.
与一个构造函数一起使用
在构造函数中,也可以使用this关键字来调用同一个类中的另一个构造函数。 这样做被称为显式构造函数调用。 这里是另外一个Rectangle类,与Objects部分中的不同。
public class Rectangle { private int x, y; private int width, height; public Rectangle() { this(0, 0, 0, 0); } public Rectangle(int width, int height) { this(0, 0, width, height); } public Rectangle(int x, int y, int width, int height) { this.x = x; this.y = y; this.width = width; this.height = height; }
}
这个类包含一组构造函数。 每个构造函数初始化矩形的一些或全部成员variables。 构造函数为初始值不是由参数提供的任何成员variables提供默认值。 例如,无参数构造函数使用四个0值调用四参数构造函数,双参数构造函数使用两个0值调用四参数构造函数。 和以前一样,编译器根据参数的数量和types决定调用哪个构造函数。
如果存在,则另一个构造函数的调用必须是构造函数中的第一行。
super()&this()
- super() – 调用父类的构造函数。
- this() – 调用相同的类构造函数。
注意:
-
我们可以只在构造函数中使用super()和this()而不在其他任何地方,任何试图这样做都会导致编译时错误。
-
我们必须保持super()或this()作为构造函数的第一行,但不能同时使用。
超级和这个关键字
- 超级 – 调用父类成员(variables和方法)。
- 这个 – 调用相同的类成员(variables和方法)。
注意:除了静态区域(静态块或方法)外,我们可以在类中的任何地方使用这两种方法,任何尝试这样做都会导致编译时错误。
这似乎是一个人提出一个问题,即每个人都只能看到一个可能的答案。 然而,这个人称每个答案都是不答复的,所以每个人都会在同一个答案上尝试一个不同的变体,因为似乎只有一个答案。
所以,一个人开始与A是一个类,B是它的子类。 下一个从C开始的人是一个类,B是它的子类。 第三个人有一点不同的回答。 A是一个类,B延伸A.然后第四个说A是一个类,它被定义为B。 或者动物是一个类,狗是一个子类。 或者民族是一个阶级,中国是民族的特例。
或者更好的是,曼是一个阶级,而克拉克·肯特是曼的一个子类。 所以,超人…不…这不符合Java的工作….
那么,至less有另一个尝试提出一个不同的描述,没有人提出可能解释不同的事情。 Arggghhhh。
在我看来,除了我之外,每个人的解释都是有效的。