背景:对基类和派生类有更清晰的认识。

从外部看来,派生类是一个与基类具有相同接口的新类,或许还会有一些额外的的方法和域 。但继承并不仅仅是类的复用。当创建了一个派生类的对象时,该类包含了一个基类的子对象。这个子对象和你用基类直接创建的对象没有什么两样。

二者的区别在于,后者来自于外部,而基类的子对象来自于派生类对象的内部。对基类的子对象初始化时至关重要的,而且也只有一种方法来保证这一点,那就是在派生类的构造器中调用基类的构造器,而基类的构造器具有执行基类初始化所需的所有能力和知识。

示例

在无参构造器时, java会自动在派生类的构造器中插入对基类的构造器的调用。

public class Humans {
Humans(){
System.out.println("我是人!");
} }
public class Student extends Humans{  

    Student(){
System.out.println("我是学生!");
} }
public class test {
public static void main(String args[]){
new Student();
}
}

输出结果为:

      我是人!

     我是学生!

可以发现,总是基类的构造器先被初始化。

示例

但是当构造器有参数时,那就必须使用关键字super现实地编写调用基类构造器的代码,并且匹配适当的参数列表。

public class Humans {  

    private String name;  

    Humans(String name){
System.out.println("我是叫"+name+"的人");
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} }
public class Student extends Humans{  

    private String name;  

    Student(String name){
super(name);
System.out.println("我是学生!");
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}
public class test {
public static void main(String args[]){
new Student("zhangsan");
}
}

输出结果:

我是叫zhangsan的人

我是学生!

如果注释掉上面的super(name);将会报错。原因是派生类必须调用基类构造器。因为实例化派生类时,基类也会被实例化,如果不调用基类的构造器,基类将不会被实例化,所以派生类没有调用基类构造器会报错。

但是如果Humans的代码变成这样就不会错。如下代码:

public class Humans {  

    private String name;  

    Humans(){
System.out.println("我是人!");
}
Humans(String name){
System.out.println("我是叫"+name+"的人");
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} }
public class Student extends Humans{  

    private String name;  

    Student(String name){
//super(name);
System.out.println("我是学生!");
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}
public class test {
public static void main(String args[]){
new Student("zhangsan");
}
}

输出结果为:

        我是人!

        我是学生!

原因是,如果基类有一个无参的构造器,就算派生类不用super显示调用基类的构造函数,编译器也会自动去调用基类的无参构造函数。

所以上面的代码不会报错,输出结果也不是

        我是叫zhangsan的人

        我是学生!

而是

        我是人!

        我是学生!

示例

派生类继承了基类的所有public和protected属性和方法,代码如下:

public class Humans {  

    public String sex;  

    protected int age ;  

    private String name;  

    Humans(String sex,String name,int age){
this.sex = sex;
this.name = name;
this.age = age;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} }
public class Student extends Humans{  

    Student(String sex ,String name,int age){
super(sex,name,age);
}
}
public class test {
public static void main(String args[]){
Student s = new Student("男","zhangsan",10);
System.out.println(s.sex);
System.out.println(s.name);
System.out.println(s.age);
}
}

上面的System.out.println(s.name);会报错,因为name是private属性,如需访问,采用get方法:

System.out.println(s.getName())

输出结果为:

男

zhangsan

10 

示例

如果派生类定义了和基类一样的属性或方法,将覆盖基类的属性和方法。如将student改为如下代码:

public class Student extends Humans{  

    public String sex;  

    protected int age ;  

    private String name;  

    Student(String sex ,String name,int age){
super(sex,name,age);
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}

输出结果为:

null

null

0

因为只有基类的属性在构造时赋值了,派生类的没有,当访问这些属性时,访问的是派生类的属性,所以全为null或者0。

只有当派生类的属性也被实例化时,才会得到属性的值。代码改为如下:

public class Student extends Humans{  

    public String sex;  

    protected int age ;  

    private String name;  

    Student(String sex ,String name,int age){
super(sex,name,age);
this.sex = sex;
this.name = name;
this.age = age;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}

输出结果为:


zhangsan
10  

要注意的是,super必须在构造器的最前面,不然会报错

Java基类和派生类的更多相关文章

  1. 详解C++中基类与派生类的转换以及虚基类

    很详细!转载链接 C++基类与派生类的转换在公用继承.私有继承和保护继承中,只有公用继承能较好地保留基类的特征,它保留了除构造函数和析构函数以外的基类所有成员,基类的公用或保护成员的访问权限在派生类中 ...

  2. 不可或缺 Windows Native (21) - C++: 继承, 组合, 派生类的构造函数和析构函数, 基类与派生类的转换, 子对象的实例化, 基类成员的隐藏(派生类成员覆盖基类成员)

    [源码下载] 不可或缺 Windows Native (21) - C++: 继承, 组合, 派生类的构造函数和析构函数, 基类与派生类的转换, 子对象的实例化, 基类成员的隐藏(派生类成员覆盖基类成 ...

  3. (转) C++中基类和派生类之间的同名函数的重载问题

    下面有关派生类与基类中存在同名函数 fn: class A { public: void fn() {} void fn(int a) {} }; class B : public A { publi ...

  4. c++中基类与派生类中隐含的this指针的分析

    先不要看结果,看一下你是否真正了解了this指针? #include<iostream> using namespace std; class Parent{ public: int x; ...

  5. C++学习21 基类和派生类的赋值

    在C/C++中,经常会发生数据类型转换,例如整型数据可以赋值给浮点型变量,在赋值之前,先把整型数据转换为浮点型:反过来,浮点型数据也可以赋值给整型变量. 数据类型转换的前提是,编译器知道如何对数据进行 ...

  6. 基类和派生类--this

    基类指针在程序运行的时候的确指向的是一个派生类的对象,但指针的类型仍然是基类指针.C++是一种强类型语言,因此不能用基类指针类型的指针直接调用派生类:而且,同一个类可能有多种不同的派生类,因此不知道实 ...

  7. C++:基类与派生类对象之间的赋值兼容关系

    4.5 基类与派生类对象之间的赋值兼容关系 在一定条件下,不同类型的数据之间可以进行类型转换,例如可以将整型数据赋给双精度型变量. 在赋值之前,先把整型数据转换为双精度型数据,然后再把它双精度型变量. ...

  8. C++:基类和派生类

    4.1 派生类的声明 继承实例如下: class Person{ //声明基类Person public: void print() { cout<<"name:"&l ...

  9. C++基类和派生类之间的转换

    本文讲解内容的前提是派生类继承基类的方式是公有继承,关键字public 以下程序为讲解用例. #include<iostream> using namespace std; class A ...

随机推荐

  1. QQ群管理员申请帖(本次截止日期为2017-03-25)

    本帖专门为技术交流群申请管理员专用. 管理员的权利: 1.有权在成员违规的情况下直接剔除. 2.有权加入多个交流群. 3.有权引人入群. 4.艾特全体是权利,但要慎用,通常情况下,没有我本人的授意,不 ...

  2. Bash Shebang 小结

    在 shell(Bash 是一种 shell) 中执行外部程序和脚本时,Linux 内核会启动一个新的进程,以便在新的进程中执行指定的程序或脚本.内核知道该如何为编译型的程序做这件事,但是对于脚本程序 ...

  3. Gerrit日常维护记录

    Gerrit代码审核工具是个好东西,尤其是在和Gitlab和Jenkins对接后,在代码控制方面有着无与伦比的优势. 在公司线上部署了一套Gerrit系统,在日常运维中,使用了很多gerrit命令,在 ...

  4. 剑指offer:二叉树中和为某一值的路径

    本来这只是一个普通的算法题,但是当初自己OJ上提交时,总是提交失败,而我自己认定程序逻辑没有任何问题.然后开始就在本机上调试,结果发现这是由于Python的对象机制而引发的.所以先把问题算法题贴出来, ...

  5. JS 实现计算一段文字中的字节数,字母数,数字数,行数,汉字数。

    看到了匹配,第一个想到了用正则表达式,哈哈,果然很方便.不过正则表达式高深莫测!我还没有研究明白啊..目前学了点皮毛.代码如下: <!DOCTYPE html PUBLIC "-//W ...

  6. 如何启动Intel VT-X及合理利用搜索

    昨天安装Vmware的时候不幸遇到了Vt-X被禁用的麻烦,上网百度了一下才知道要进入Bois进行设置.说起百度就不得不提到模糊搜索这个概念.这个特性的优点和缺点可谓同等突出,有了模糊搜索大家可以在信息 ...

  7. 软工个人作业-博客作业-WEEK2

    1.是否需要代码规范:    (1)这些规范都是官僚制度下产生的浪费大家的编程时间.影响人们开发效率, 浪费时间的东西.        首先来说,从短期上和个体上来看,一个团队的代码风格必然会在一定程 ...

  8. "Linux内核分析"第七周

    可执行程序的装载 张文俊+原创作品转载请注明出处+<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.预 ...

  9. 【SE】Week3 : 四则运算式生成评分工具Extension&Release Version(附加题)

    [附加题]第四阶段目标 - 界面模块,测试模块和核心模块的松耦合. 写到这里我只想吐槽一句,哪天我能写出功能复杂且真正松耦合的模块,我应该就不用写代码了吧[手动再见.. 当然这只是强调下松耦合和代码复 ...

  10. maven私服 Nexus2.x.x私服安装配置

    一.Nexus的下载和安装 1.下载nexus ,下载地址:https://www.sonatype.com/download-oss-sonatype  2.打开目录nexus-2.x.x-xx-b ...