Java中super关键字的语法知识点及案例
1. 定义
super是Java中的一个关键字,主要用于引用当前对象的父类或超类。通过super,可以在子类中访问父类的成员变量、方法和构造函数。
2. 主要用途
- 访问父类的成员变量:当子类与父类有同名的成员变量时,可以使用super关键字来明确访问父类的成员变量。
- 调用父类的构造方法:在子类的构造方法中,可以使用super关键字来调用父类的构造方法,以初始化父类的成员变量或执行父类构造函数的逻辑。
- 调用父类的方法:在子类中,可以通过super关键字调用父类的方法,特别是在子类重写了父类的方法时,仍然可以通过super来调用父类的方法。
3. 使用场景与注意事项
- 构造方法中的使用:super()只能出现在子类构造方法的第一行,用于调用父类的构造方法。如果子类构造方法中没有显式调用super()或this(),系统会默认调用父类的无参数构造方法。
- 不能用于静态方法:super关键字不能用于静态方法中。
- this()和super()不能共存:在构造方法中,this()和super()不能同时出现,它们都是只能出现在构造方法的第一行。
4. 案例代码
案例一:访问父类的成员变量
class Parent {
int x = 10;
}
class Child extends Parent {
int x = 20;
void display() {
System.out.println(super.x); // 访问父类的x变量,输出10
System.out.println(this.x); // 访问子类的x变量,输出20
}
}
public class Main {
public static void main(String[] args) {
Child child = new Child();
child.display();
}
}
案例二:调用父类的构造方法
class Parent {
int x;
Parent(int x) {
this.x = x;
}
}
class Child extends Parent {
int y;
Child(int x, int y) {
super(x); // 调用父类构造函数,将x赋值
this.y = y;
}
@Override
public String toString() {
return "Child{" + "y=" + y + ", x=" + x + '}';
}
}
public class Main {
public static void main(String[] args) {
Child child = new Child(10, 20);
System.out.println(child.toString());
}
}
案例三:调用父类的方法
class Parent {
void print() {
System.out.println("Parent's print method");
}
}
class Child extends Parent {
@Override
void print() {
super.print(); // 调用父类的print方法
System.out.println("Child's print method");
}
}
public class Main {
public static void main(String[] args) {
Child child = new Child();
child.print();
}
}
案例四:子类与父类有同名的成员变量
class Animal {
String name = "Animal";
}
class Dog extends Animal {
String name = "Dog";
void printNames() {
System.out.println(super.name); // 输出父类Animal的name
System.out.println(this.name); // 输出子类Dog的name
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.printNames();
}
}
案例五:子类构造方法调用父类构造方法并初始化成员变量
class Animal {
String name;
public Animal(String name) {
this.name = name;
}
public void eat() {
System.out.println(name + " is eating");
}
}
class Dog extends Animal {
String breed;
public Dog(String name, String breed) {
super(name); // 调用父类Animal的构造方法
this.breed = breed;
}
public void bark() {
System.out.println(name + " is barking");
}
@Override
public void eat() {
super.eat(); // 调用父类Animal的eat方法
System.out.println(name + " is eating bones");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog("Rex", "Labrador");
dog.eat(); // 调用子类Dog的eat方法
dog.bark(); // 调用子类Dog的bark方法
}
}
通过以上案例代码,可以更清晰地理解super关键字在Java中的使用方法和场景。
当然可以,以下是一些额外的关于super
关键字的例子,这些例子将展示super
在不同情境下的应用。
例子一:在多重继承链中使用super
虽然Java不支持多重继承(即一个类不能同时继承多个类),但可以通过继承的传递性(一个类继承自另一个已经继承自其他类的类)来模拟多重继承的效果。在这种情况下,super
可以用来引用直接父类或更远的祖先类。
class Grandparent {
void display() {
System.out.println("Grandparent display()");
}
}
class Parent extends Grandparent {
@Override
void display() {
System.out.println("Parent display()");
}
}
class Child extends Parent {
@Override
void display() {
super.display(); // 调用直接父类Parent的display()
// 如果想调用Grandparent的display(),可以使用以下方式(但不直接通过super)
// ((Grandparent)this).display(); // 强制类型转换,不推荐这样做,因为它破坏了封装性
// 一个更好的做法是在Parent类中调用Grandparent的display()
}
void callGrandparentDisplay() {
// 在这里,我们假设Parent类已经正确地调用了Grandparent的display()
super.display(); // 这将调用Parent的display(),而Parent可以进一步调用Grandparent的
}
}
// 注意:在Child类中直接调用Grandparent的display()通常不是最佳实践。
// 更好的做法是在Parent类中处理这种调用,或者在Child类中通过其他方式(如方法参数、组合等)来实现。
public class Main {
public static void main(String[] args) {
Child child = new Child();
child.display(); // 输出:Parent display()
// child.callGrandparentDisplay(); // 这将仍然输出:Parent display(),因为Parent没有调用Grandparent的
}
}
// 为了完整性,我们可以修改Parent类来正确调用Grandparent的display()
class ParentExtended extends Grandparent {
@Override
void display() {
super.display(); // 现在Parent调用了Grandparent的display()
System.out.println("Parent display() after calling Grandparent");
}
}
// 然后让Child继承ParentExtended而不是Parent
// class ChildExtended extends ParentExtended { ... }
// 注意:上面的代码示例是为了说明目的而编写的,并没有完整地展示多重继承链中super的使用。
// 在实际编程中,你应该避免直接操作远祖类的方法,而是通过设计良好的继承层次结构来间接实现。
注意:上面的代码示例中关于直接调用Grandparent
的display()
方法的注释部分并不是最佳实践。在实际编程中,你应该避免在子类中直接调用远祖类的方法,因为这可能会破坏封装性和代码的可维护性。相反,你应该通过设计良好的继承层次结构来间接实现这一功能,比如让Parent
类调用Grandparent
类的方法,并在Child
类中通过super
来调用Parent
类的方法。
例子二:在方法覆盖中使用super来保持父类行为
当子类覆盖父类的方法时,如果仍然想保留父类方法的行为,可以在子类方法内部调用super
来实现。
class Animal {
void makeSound() {
System.out.println("Some generic animal sound");
}
}
class Dog extends Animal {
@Override
void makeSound() {
super.makeSound(); // 调用父类的makeSound()方法
System.out.println("Woof! Woof!"); // 添加子类特有的行为
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.makeSound(); // 输出:Some generic animal sound\nWoof! Woof!
}
}
在这个例子中,Dog
类覆盖了Animal
类的makeSound()
方法,但在覆盖的方法中仍然调用了父类的makeSound()
方法,以保留父类的行为,并添加了子类特有的行为。
这些例子应该能帮助你更好地理解super
关键字在Java中的使用。
super
关键字在Java编程中有多个重要的应用场景,以下是其主要应用场景的归纳:
1. 调用父类构造方法
- 在子类的构造方法中,可以使用
super()
来调用父类的构造方法。这是确保父类属性被正确初始化的关键步骤。 super()
调用必须在子类构造方法的第一行,且一个构造方法中只能有一个super()
调用。
2. 访问父类成员变量
- 当子类中定义了一个与父类同名的成员变量时,可以使用
super
关键字来引用父类的成员变量。 - 这有助于在子类中区分和访问父类与子类的同名变量。
3. 调用父类方法
- 如果子类覆盖了父类的方法,但仍然想调用父类的方法,可以使用
super.method_name()
语法。 - 这在保留父类行为的同时,允许子类添加或修改特定的行为。
4. 表示父类类型的引用
- 在子类的实例方法中,
super
可以作为一个引用变量来使用,它引用了当前对象的父类类型。 - 这使得子类可以像操作父类实例一样调用其方法或访问其属性。
5. 在多重继承模拟中的使用(虽然不是直接多重继承)
- 虽然Java不支持多重继承,但可以通过类的层次结构来模拟多重继承的效果。
- 在这种情况下,
super
可以用来引用直接父类,而父类可以进一步引用其祖先类。 - 然而,直接操作远祖类的方法通常不是最佳实践,更好的做法是通过设计良好的继承层次结构来间接实现。
示例代码
以下是一些示例代码,展示了super
关键字在不同应用场景中的使用:
// 示例1:调用父类构造方法
class Parent {
int number;
Parent(int number) {
this.number = number;
}
}
class Child extends Parent {
String name;
Child(int number, String name) {
super(number); // 调用父类的构造方法
this.name = name;
}
}
// 示例2:访问父类方法
class Animal {
void makeSound() {
System.out.println("Some generic animal sound");
}
}
class Dog extends Animal {
@Override
void makeSound() {
super.makeSound(); // 调用父类的方法
System.out.println("Woof! Woof!");
}
}
// 示例3:访问父类变量
class ParentClass {
int value = 10;
}
class ChildClass extends ParentClass {
int value = 20;
void printValues() {
System.out.println("Parent's value: " + super.value); // 访问父类的变量
System.out.println("Child's value: " + this.value);
}
}
综上所述,super
关键字在Java编程中扮演着重要角色,它允许子类直接访问和操作父类的成员,有助于实现代码的重用和多态性。