super:
1.定义:
在 JAVA 类中使用 super 来引用父类的成分,用 this 来引用当前对象,如果一个类从另外一个类继承,我们 new 这个子类的实例对象的时候,这个子类对象里面会有一个父类对象。怎么去引用里面的父类对象呢?使用 super 来引用,this 指的是当前对象的引用,super 是当前对象里面的父对象的引用。
2.使用:
super 关键字同 this 相似,调用时同样有三种应用:
调用父类可调用属性
调用父类可调用方法
调用父类对应构造方法
应用一:调用父类属性:
super 关键字一般用于含有继承关系,我们还是用例子演示具体调用方式,如现在有一父类 Person,该类含有属性(id,name,sex),还有一子类 Student,该类继承 Person 类,并含有自己特有的属性分数(StudentScore),那么 我们如何在子类中调用父类定义的共同属性呢?代码如下:
父类:
package cn.hz;
/**
* @author hz
* @version 1.0
* 父类
*/
public class Person {
public Integer id; //属性:学生编号
public String name; //属性:学生姓名
public String sex; //属性:学生性别
}
复制代码
子类:
package cn.hz;
/**
* @author hz
* @version 1.0
*/
public class Student extends Person {
public Integer studentScore; //属性:学生分数
public void show(){
System.out.println("学生信息如下:姓名:"+super.name+",性别:"+
super.sex+"编号:"+super.id+",分数:"+this.studentScore);
}
}
复制代码
在子类中调用父类定义属性,语法如下:
特别注意,子类在调用父类属性时,一定注意属性权限修饰符(具体使用见见前面章节继承中权限修饰符表),并不是父类的所有属性子类都能通过 super 调用,如对父类进行封装,属性使用 private 完成封装,在这种场合我们就无法直接调用父类属性,如何操作呢?需要调用父类的方法进行操作。
应用二:调用父类方法:
子类继承父类,则可以使用父类的属性和方法,前面我们看了子类如何调用父类的属性,接着我们来看看子类如何调用父类的方法:
父类:
package cn.hz;
/**
* @author hz
* @version 1.0
* 父类: 封装
*/
public class Person {
private Integer id; //属性:学生编号
private String name; //属性:学生姓名
private String sex; //属性:学生性别
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public void test(){
System.out.println("父类方法");
}
}
复制代码
子类:
package cn.hz;
/**
* @author hz
* @version 1.0
*/
public class Student extends Person {
public Integer studentScore; //属性:学生分数
public void show(){
System.out.println("学生信息如下:姓名:"+super.getName()+",性别:"+
super.getSex()+"编号:"+super.getId()+",分数:"+this.studentScore);
}
public void test2(){
System.out.println("调用父类方法");
super.test();
}
}
复制代码
上述代码父类 Person 完成了封装,子类无法调用父类属性,但是子类可以通过调用父类中对属性提供的公共方法 set 方法从而获取父类的值,在父类中还定义了一个普通方法,子类同样可以通过关键字 super 进行调用。
注意: 在该处因为子类已经将父类的属性和方法继承了,所以在调用父类的方法时 super 省略或者使用 this 进行替代都可以(实际开发中一般直接省略),代码如下:
super 关键字省略:
package cn.hz;
/**
* @author hz
* @version 1.0
*/
public class Student extends Person {
public Integer studentScore; //属性:学生分数
public void show(){
System.out.println("学生信息如下:姓名:"+getName()+",性别:"+
getSex()+"编号:"+getId()+",分数:"+this.studentScore);
}
public void test2(){
System.out.println("调用父类方法");
test();
}
}
复制代码
使用 this 关键字:
package cn.hz;
/**
* @author hz
* @version 1.0
*/
public class Student extends Person {
public Integer studentScore; //属性:学生分数
public void show(){
System.out.println("学生信息如下:姓名:"+this.getName()+",性别:"+
this.getSex()+"编号:"+this.getId()+",分数:"+this.studentScore);
}
public void test2(){
System.out.println("调用父类方法");
this.test();
}
}
复制代码
应用三:调用父类构造方法:
子类在创建对象时需要使用构造方法,并且一定会使用父类的构造方法,我们来看看子类是如何调用父类的构造方法的?
父类:
package cn.hz;
/**
* @author hz
* @version 1.0
* 父类: 封装
*/
public class Person {
private Integer id; //属性:学生编号
private String name; //属性:学生姓名
private String sex; //属性:学生性别
//set/get省略
public Person() {
}
public Person(String name) {
this.name = name;
}
public Person(Integer id, String name) {
this.id = id;
this.name = name;
}
public Person(Integer id, String name, String sex) {
this.id = id;
this.name = name;
this.sex = sex;
}
}
复制代码
子类:
package cn.hz;
/**
* @author hz
* @version 1.0
*/
public class Student extends Person {
public Integer studentScore; //属性:学生分数
public Student(Integer studentScore) {
this.studentScore = studentScore;
}
public Student(String name, Integer studentScore) {
super(name);
this.studentScore = studentScore;
}
public Student(Integer id, String name, Integer studentScore) {
super(id, name);
this.studentScore = studentScore;
}
public Student(Integer id, String name, String sex, Integer studentScore) {
super(id, name, sex);
this.studentScore = studentScore;
}
}
复制代码
通过上方代码我们可得调用父类的构造方法:
注意,子类调用父类的构造方法时,同子类自己构造方法之间相互调用一样,该代码一定是在构造方法的第一行
3.案例分析:
案例一: 以下代码运行结果什么?
package cn.hz;
/**
* @author hz
* @version 1.0
* 父类: 封装
*/
public class Person {
private Integer id; //属性:学生编号
private String name; //属性:学生姓名
private String sex; //属性:学生性别
//set/get省略
public Person() {
System.out.println("父类无参方法");
}
public Person(String name) {
this.name = name;
System.out.println("父类name属性构造方法");
}
public Person(Integer id, String name) {
this();
this.id = id;
this.name = name;
System.out.println("父类id,name属性构造方法");
}
}
复制代码
package cn.hz;
/**
* @author hz
* @version 1.0
*/
public class Student extends Person {
public Integer studentScore; //属性:学生分数
public Student() {
System.out.println("子类无参构造方法");
}
public Student(String name, Integer studentScore) {
super(name);
this.studentScore = studentScore;
System.out.println("子类属性name构造方法");
}
public Student(Integer id, String name, Integer studentScore) {
super(id, name);
this.studentScore = studentScore;
System.out.println("子类属性name,id构造方法");
}
}
复制代码
package cn.hz;
/**
* @author hz
* @version 1.0
*/
public class StudentTest {
public static void main(String[] args) {
//创建学生对象
Student student1=new Student();
//创建学生对象
Student student2=new Student("zs",80);
//创建学生对象
Student student3=new Student(10001,"ls",90);
}
}
复制代码
刚看到这个案例,可能很多同学感觉不知从何下手,本案例主要考察大家对对象创建过程的掌握及 super 和 this 关键字的熟练度,首先我们分析 student1 对象的创建,子类含有无参构造方法,虽然子类无参构造方法没有显式调用父类的构造方法,但是子类在创建对象时一定会调用调用父类构造方法,所以 student1 的创建会调用子类无参构造,父类无参构造;
student2 创建时会调用子类自己对应参数的构造方法,首行含有 super(name),则会调用父类对应的构造方法,父类中含有对应的构造方法则直接执行。
student3 创建时会调用子类对应的参数的构造方法,首行含有 super(id,name),则会调用父类对应的构造方法,父类中含有对应构造方法则执行,但是重点来了,在父类的构造方法中,首行出现了 this();这是很多同学容易出现错误的地方,this()表示父类调用自己的无参构造方法,则整个过程调用执行了三个构造方法,最终执行结果如下:
小结:
子类调用父类的构造方法是,同子类自己构造方法之间相互调用一样,该代码一定位于构造方法第一行;
子类构造方法中如果显式调用对应构造方法,则创建对象时先调用父类对应构造方法,则调用子类构造方法。
子类构造方法中如果没有显式调用父类的构造方法,则默认调用父类的无参构造方法,子类创建对象时一定会调用父类的构造方法。
评论