继承
继承:就是子类继承父类的属性和行为,使得子类对象可以直接具有与父类相同的属性、相同的行为。子类可以直接访问父类中的非私有的属性和行为。
classs 类1 extends 类2
{
//代码
}
继承的好处:
class C extends A{} //ok
class C extends A,B... //error
- Java支持多重继承(继承体系)。
class A{}
class B extends A{}
class C extends B{}
方法重写:
方法重写 :子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效果,也称为重写或者复写。声明不变,重新实现。
1)旧手机功能:基本的打电话,发信息
2)新手功功能:基本的打电话下支持视频通话,基本的发信息下支持发送语音和图片。
定义旧手机类,实现打电话,发信息功能。定义新手机类继承老手机,重写打电话和发信息功能。
package com.itheima.sh.d_extends_04;//1.定义一个旧手机类public class OldPhone { //2.在旧手机类中定义打电话 public void call(){ System.out.println("旧手机只能打电话"); } //和发短信功能 public void sendMessage(){ System.out.println("旧手机只能发短信"); }}package com.itheima.sh.d_extends_04;// 3.定义一个新手机类继承旧手机public class NewPhone extends OldPhone{ //4.在子类即新手机类中对旧手机的打电话和发短信功能进行重写即重新编写 //书写要重写的方法名回车 @Override public void call() { //调用的是父类的功能 super.call(); System.out.println("新手机除了打电话还可以视频通话"); } @Override public void sendMessage() { //调用的是父类的功能 super.sendMessage(); System.out.println("新手机除了发短信还可以发图片"); }}package com.itheima.sh.d_extends_04;/* 步骤: 1.定义一个旧手机类 2.在旧手机类中定义打电话和发短信功能 3.定义一个新手机类继承旧手机 4.在子类即新手机类中对旧手机的打电话和发短信功能进行重写即重新编写 5.在测试类中创建子类对象,使用对象调用方法 */public class Test01 { public static void main(String[] args) { //5.在测试类中创建子类对象,使用对象调用方法 NewPhone np = new NewPhone(); np.call(); np.sendMessage(); }}
@Override重写注解
- Override:注解,重写注解校验!
- 这个注解标记的方法,就说明这个方法必须是重写父类的方法,否则编译阶段报错。
- 建议重写都加上这个注解,一方面可以提高代码的可读性,一方面可以防止重写出错!
注意事项
- 方法重写是发生在子父类之间的关系。
- 子类方法覆盖父类方法,必须要保证权限大于等于父类权限。
- 子类方法覆盖父类方法,返回值类型、函数名和参数列表都要一模一样。
继承后的特点—构造器
引入
- 构造器的名字是与类名一致的。所以子类是无法继承父类构造方法的。
- 构造器的作用是初始化对象成员变量数据的。所以子类的初始化过程中,必须先执行父类的初始化动作。子类的构造方法中默认有一个super() ,表示调用父类的构造方法,父类成员变量初始化后,才可以给子类使用。(先有爸爸,才能有儿子)
需求:
根据以下代码画图说明子父类构造函数的特点。
1)创建一个子类Zi和一个父类Fu,让这个子类来继承这个Fu类;
2)在Fu类中定义一个成员变量x并赋值为3,然后创建Fu类构造代码块,在这个Fu类代码块中打印x的值;
3)在Fu类中定义一个一般函数show,也打印x的值;
4)在Fu类中定义一个无参构造函数,随便打印一句话;
5)在Zi类中定义一个成员变量y并赋值为10,同样定义一个构造代码块,分别写两个打印语句打印x和y的值;
6)在子类中复写父类中show函数,并写两句语句,分别打印x和y的值;
7)在子类中定义一个构造函数,使用super()调用父类无参构造函数,在子类构造函数中打印一句话,调用show函数;
8)定义一个测试类ConstructorDemo ,在这个类中创建Zi类的对象;
//继承中的构造函数细节
class Fu
{
int x = 3;
{
System.out.println("Fu 构造代码块 x="+x);
}
Fu()
{
//super();
System.out.println("Fu的构造函数执行");
}
void show()
{
System.out.println("Fu show x="+x);
}
}
class Zi extends Fu
{
int y = 10;
{
System.out.println("Zi 的构造代码块 x="+x);
System.out.println("Zi 的构造代码块 y="+y);
}
Zi()
{
super();
System.out.println("Zi的构造函数执行。。。。。");
show();
}
void show()
{
System.out.println("Zi show x="+x);
System.out.println("Zi show y="+y);
}
}
class ConstructorDemo
{
public static void main(String[] args)
{
Zi z = new Zi();
}
}
super(…)和this(…)
super和this的用法格式:
this.成员变量 — 本类的 super.成员变量 — 父类的
this.成员方法名() — 本类的
super.成员方法名() — 父类的
class Person {
private String name ="凤姐";
private int age = 20;
public Person() {
System.out.println("父类无参");
}
public Person(String name , int age){
this.name = name ;
this.age = age ;
}
// getter/setter省略
}
class Student extends Person {
private double score = 100;
public Student() {
//super(); // 调用父类无参构造器,默认就存在,可以不写,必须再第一行
System.out.println("子类无参");
}
public Student(String name , int age,double score) {
super(name ,age);// 调用父类有参构造器Person(String name , int age)初始化name和age
this.score = score;
System.out.println("子类有参");
}
// getter/setter省略
}
public class Demo07 {
public static void main(String[] args) {
// 调用子类有参数构造器
Student s2 = new Student("张三",20,99);
System.out.println(s2.getScore()); // 99
System.out.println(s2.getName()); // 输出 张三
System.out.println(s2.getAge()); // 输出 20
}
}
注意
子类的每个构造方法中均有默认的super(),调用父类的空参构造。手动调用父类构造会覆盖默认的super()。**super() 和 this() 都必须是在构造方法的第一行,所以不能同时出现。**
super(..)是根据参数去确定调用父类哪个构造器的。
super(…)案例图解
父类空间优先于子类对象产生 在每次创建子类对象时,先初始化父类空间,再创建其子类对象本身。目的在于子类对象中包含了其对应的父类空间,便可以包含其父类的成员,如果父类成员非private修饰,则子类可以随意使用父类成员。代码体现在子类的构造器调用时,一定先调用父类的构造器。理解图解如下:
this(…)用法演示
this(…)
- 默认是去找本类中的其他构造器,根据参数来确定具体调用哪一个构造器。
为了借用其他构造器的功能。 ```java package com.itheima._08this和super调用构造器; class Student{ private String name ; private int age ; private char sex ;
public Student() { // 很弱,我的兄弟很牛逼啊,我可以调用其他构造器:Student(String name, int age, char sex)
this("徐干",21,'男');
}
public Student(String name, int age, char sex) {
this.name = name ;
this.age = age ;
this.sex = sex ;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
} }
/**
- this(…):
- 默认是去找本类中的其他构造器,根据参数来确定具体调用哪一个构造器。
- 为了借用其他构造器的功能。 / public class ThisDemo01 { public static void main(String[] args) { Student xuGan = new Student(); System.out.println(xuGan.getName()); // 输出:徐干 System.out.println(xuGan.getAge());// 输出:21 System.out.println(xuGan.getSex());// 输出: 男 } }
```java
- 子类的每个构造方法中均有默认的super(),调用父类的空参构造。手动调用父类构造会覆盖默认的super()。
- super() 和 this() 都必须是在构造方法的第一行,所以不能同时出现。
- super(..)和this(...)是根据参数去确定调用父类哪个构造器的。
- super(..)可以调用父类构造器初始化继承自父类的成员变量的数据。
- this(..)可以调用本类中的其他构造器。