在前面的学习中,我们了解到子类可以重写父类的方法和隐藏父类的属性。子类的方法中不能直接引用父类隐藏的属性也不能直接调用父类中隐藏的方法。如果子类方法中需要引用父类中隐藏了的属性,或者调用父类中隐藏了的方法,该怎么办呢?在java中,是通过super关键字来解决这个问题,我们可以通过super访问父类隐藏的属性或者调用父类隐藏的方法。此外,通过super关键字我们还可以在子类的构造方法中调用父类的构造方法。
package com.oop.Rew;
//父类是银行类 有三个属性
class Bank {
int savedMoney; //余额
int year; //存款年限
double interest;//利息
//银行内有一个计算利息的方法
public double computerInterest() {
interest=year*0.035*savedMoney;
System.out.printf("%d元存在银行%d年的利息:%f元\n",
savedMoney,year,interest);
return interest;
}
}
//子类是建设银行类,从银行类中派生而来
class ConstructionBank extends Bank {
double year;//建设银行类中定义了一个存款年限的属性,该属性隐藏了其父类银行类的存款年限的属性
public double computerInterest() {
//调用了父类的属性
super.year=(int)year;
double remainNumber=year-(int)year;
int day=(int)(remainNumber*1000);
//调用了父类的方法 interest=super.computerInterest()+day*0.0001*savedMoney;
System.out.printf("%d元存在建设银行%d年零%d天的利息:%f元\n",
savedMoney,super.year,day,interest);
return interest;
}
}
public class Example03 {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
int amount=5000;
//在主类中,我们定义一个建设银行类对象,设置其
ConstructionBank bank=new ConstructionBank();
bank.savedMoney=amount;
bank.year=5.216;
double interest=bank.computerInterest();
System.out.println("银行利息 = " + interest);
}
}
package com.oop.Rew;
class student {
int number;String name;
student() {
}
student(int number,String name) {
//this 指向自己的引用
this.number=number;
this.name=name;
System.out.println("我的名字是:"+name+ "学号是:"+number);
}
}
class UniverStudent extends student {
boolean married;
UniverStudent(int number,String name,boolean b) {
//调用学生类(也就是父类)的构造方法,用于初始化 number和name
super(number,name);
married=b;
System.out.println("婚否="+married);
}
}
public class Example05 {
public static void main(String[] args) {
UniverStudent zhang=new UniverStudent(9901,"何晓林",false);
}
}
super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。
this关键字:指向自己的引用。
super注意点:
1.super调用父类的构造方法,必须在构造方法的第一行
2.super必须只能出现在子类的方法或者构造方法中!
3.super和this不能同时调用构造方法!
VS this:
代表的对象不同:
this:代表本身调用者这个对象
super:代表父类对象的引用
前提:
this:没有继承也可以使用
super:只能在继承条件下才可以使用
构造方法的区别:
this();本类的构造
super();父类的构造
子类对象在实例化时会默认先去调用父类中的无参构造方法,之后再调用本类中的相应构造方法。
子类是不继承父类的构造器(构造方法或者构造函数)的,它只是调用(隐式或显式)。如果父类的构造器带参,则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表。(可参考最后一条规则示例:)
如果父类构造器无参,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器。
如下:
//父类:
package com.oop.Test05;
public class Person{
//父类的无参构造
public Person() {
System.out.println("父类无参构造执行了");
}
}
//子类:
package com.oop.Test05;
public class Student extends Person{
//子类的无参构造
public Student() {
//super();可显式可隐藏,若显式,则必须放在第一行
System.out.println("子类的无参构造执行了");
}
}
//测试类:
package com.oop;
import com.oop.Test05.Student;
public class Application {
public static void main(String[] args) {
Student student = new Student();
}
}
输出:
父类无参构造执行了
子类的无参构造执行了
1.子类的构造方法中没有通过super显式调用父类的有参构造方法,也没有通过this显式调用自身的其他构造方法,则系统会默认先调用父类的无参构造方法。在这种情况下,super()语句有没有都一样;
但是注意:若父类显式定义了有参构造方法,但未显式定义无参构造,此时父类中的无参构造方法就被干掉了,此时既无法使用super();
语句调用父类的无参构造, 同时子类也无法定义自己的无参构造。在这种情况下,super();
语句,写了也没用,编译器报错,代码无法通过。不过我们只是无法调用无参,但是可以调用父类的有参构造。
可以通过下面的方法调用:(可参考最后一条规则示例:)
super(参数);
//参数列表匹配对应的有参构造
2.如果子类的构造方法中通过super显式调用父类的有参构造方法,此时父类无参构造方法不会被执行。
如下:
//父类:
package com.oop.Test05;
public class Person{
//父类的无参构造
public Person() {
System.out.println("父类无参构造执行了");
}
//父类的有参构造
public Person(String name) {
System.out.println("父类有参构造执行了");
}
}
//子类:
package com.oop.Test05;
public class Student extends Person{
//子类的无参构造
public Student() {
super("樱");
System.out.println("子类的无参构造执行了");
}
}
//测试类:
package com.oop;
import com.oop.Test05.Student;
public class Application {
public static void main(String[] args) {
Student student = new Student();
}
}
输出:
樱
父类有参构造执行了
子类的无参构造执行了
3.如果子类的构造方法中通过this显式调用自身的其他构造方法,在相应构造方法中应满足:this语句放在第一行。
final可以修饰属性,方法,类。
这一部分我们没有给出比较多的合适的例子,只是作为学习的总结,给出大家的一些知识,可不必死记,遇到问题再去查,次数多了自然而然也就记住了。
岁月漫长心怀热爱,携手共赴星辰大海。