1 目录及资源索引
2 实例代码分析
按照惯例,新建三个类,Person父类中的内容如下:
class Person
{
String name;
int age;
Person()
{
System.out.println("Person 的无参数构造函数");
}
Person(String name, int age)
{
this.name = name;
this.age = age;
System.out.println("Person 的有参数构造函数");
}
void eat()
{
System.out.println("吃饭");
}
}
子类 Student 中代码如下:
class Student extends Person
{
Student()
{
System.out.println("Student 的无参数构造函数");
}
}
主函数中程序代码如下:
class Test
{
public static void main(String args[])
{
Student stu = new Student();
}
}
上述代码,可以猜一下,编译后,运行结果如何?先来分析一下,主函数中只调用了Student这个类,但是 Student 又是继承的 Person 父类。
下边看一下编译后的,程序运行结果如何
首先打印出来的是 Person 父类中的无参数构造函数,接着才是 Student 子类中的无参数构造函数。即在子类的构造函数当中,必须调用父类的构造函数。
程序中如果没有写出来,编译器会默认帮你调用构造函数。
什么都不写 = 省略了 super(); 这条语句。调用的是默认的无参构造函数。
如果括号里边有参数,则调用的是对应类型的构造函数。
super 的作用,可以类比原来提到过的 this;
针对上述代码及分析,可能会提出一些疑问,为什么要这样设计,这样设计有什么好处呢?跟随老师的引导,其实就是为了消除重复代码。
在两个不同的类A,类B当中,B是A的子类,如果B中的构造函数80%都是和A相同,如果没有这个机制,会怎样,就会在B中重复的多写这80%的代码,这样就显得很冗余,也会变得复杂。
然后又有了一个新的问题,如果是一些带参的构造函数,需要怎么办?思考一下,之前说省略不写,编译器在编译的时候,会自己加上;也就是说,如果有这样的需要,就需要我们手动写出来省略掉的内容了,否则默认的都是无参数的。
下边再看一段代码,父类 Person 可以不用修改,之前在写的时候,已经是带参数的了。子类 Student 类中的代码如下:
class Student extends Person
{
int grade;
Student()
{
System.out.println("Student 的无参数构造函数");
}
// Student(int grade)
// {
// this();
// }
Student(String name, int age, int grade)
{
// this.name = name;
// this.age = age;
super(name, age); // 此处调用父类带两个参数的构造函数
this.grade = grade;
}
}
主函数中也做相应修改,代码如下:
class Test
{
public static void main(String args[])
{
Student stu = new Student("zhangsan", 18, 3);
System.out.println(stu.name);
System.out.println(stu.age);
System.out.println(stu.grade);
}
}
现在再次编译运行的结果,应该就可想而知了,具体截图如下:
发现先调用 Person 父类有参数的构造函数,然后对参数进行赋值,接着打印出结果。
3 着重注意
- 设计感悟:由于Java在设计时,子类可以继承父类的成员变量和成员函数,但是无法继承构造函数,因此再给子类一些成员变量赋值时,可能会产生重复代码,所以规定了子类的构造函数必须调用父类的构造函数。
- 使用super的时候,必须放在当前函数的首行。
4 总结
- 本节内容较少,主要是了解一些对象实例化过程;
- 子类的构造函数必须调用父类的构造函数;
- 当需要使用 super 的时候,类比 this,必须放在当前函数首行;
- 再一次体会到了面向对象语言的深处:消除重复代码;