继承是面向对象三大特征之一,也是实现软件复用的重要手段。
类的继承提高了程序代码的重用性和可扩充性,缩短了软件开发的周期。
- 继承的特点
- 重写父类的方法
- super
- 调用父类构造方法
继承的特点
[修饰符] class 子类名 extends 父类名{
//子类代码部分
}
- java 子类不能直接调用父类的构造方法
- 每个类最多只能有一个直接父类,间接父类多个。
- java.lang.Object是所有类的父类。
编写程序示范子类继承父类的特点。
public class Animal{
public double weight;
public void eat(){
System.out.println("动物在吃东西");
}
}
public class Dog extends Animal{
public void say(){
System.out.pringln(“狗叫:汪汪汪”);
}
public static void main(String[] args) {
Dog d= new Dog();
d.weight = 150; weight属性和eat方法,是从父类中继承,且访问权限没发生变化
d.eat();
d.say();
}
}
重写父类的方法
规则:“
三同一小一大”
“三同”:方法名、形参列表、返回值;
“一小”:子方法声明抛出的
异常类 < 父;
“一大”:子类方法的
访问权限 >
父;
覆盖方法和被覆盖方法么要都是类方法,要么都是实例方法。
子类覆盖父类后,子类对象无法访问父类被覆盖的方法,却可以调用:
super(实例)、父类类名(类)
private:子类定义了一个和父类同名同参同反的方法,不是重写,是新方法
子类重写父类的方法
public class Bird{
public void fly(){
System.out.println("I'm fly~");
}
}
public class Ostrich extends Bird{
//重写Bird类的fly方法----方法覆盖(override)
public void fly(){
System.out.println("I only work on the land~");
}
public static void main(String[] args){
Ostrich os = new Ostrich;
os.fly(); //调用的是Ostrich的fly?
}
}
方法重写和方法重载的区别
覆盖:父子间的关系 重载:同一类内多方法间的关系。
覆盖:两个方法间的 重载:可能有多个重载的方法。
覆盖:同名同参 重载:同名不同参。
覆盖:调用它的对象来区分方法 重载:形参表。
super
直接父类对象的默认引用。
如this不能出现在static方法中,super也不能出现在static方法中
构造方法中使用,指向该构造方法正在初始化的对象所对应的父类对象
public class Ostrich extends Bird{
… … //子类中原有的内容
public void callOverridedMethod(){
super.fly(); //输出“我在飞”
}
public static void main(String[] args){
Ostrich os = new Ostrich;
os.fly(); //奔跑
os.callOverridedMethod() //飞
}
}
属性,子类父类同名,子覆父。子方法直接访问子属性,super访问覆盖的父属性
子类属性覆盖父类属性的实例。
class BaseClass{
public int a = 5;
}
class SubClass extends BaseClass{
public int a = 7;
public void accessOwner(){
System.out.println(a); //7
}
public void accessBase(){
System.out.println(super.a); //5
}
public static void main(String[] args){
SubClass sc = new SubClass;
System.out.printlv(sc.a); //7
sc.accessOwner(); //7
sc.accessBase(); //5
}
}
某个方法中访问名为a的属性,但没有显示指定调用者,系统查找a的顺序为:
- 该方法中是否有名为a的局部变量
- 当前类中
- a 的直接父类中是否包含,依次,直到java.lang.Object类,最终不能找到则系统出现编译错误。
调用父类构造方法
子类不会继承父类的构造方法,子类构造方法里需调用父类构造方法的初始化代码。
class Base{
public double size;
public String name;
public Base(double size,String name){
this.size = size;
this.name = name;
}
}
public class Sub extends Base{
public String color;
public Sub(double size, String name, String color){
super(size,name);
this.color = color;
}
public static void main(String[] args){
Sub s = new Sub;
System.out.println(s.size + "--" +s.name + "--" + s.color);
}
}
super:调用父类的构造方法,
this :重载
第一行,不同时出现
子类构造方法调用父类构造方法:
- super调用父类构,据super传入的实参列表调用父类对应的构造方法。
- this调用本类中重载的构,据this实参列表调用本类另一个构造方法。执行本类中另一个构时即会调用父的构法。
- 没有,执行子构前,隐式调用父无参数的构法。
不管怎样,当调用父构来初始化对象时,父构总会在子构前执行
执行父构时,系统再次上溯执行其父构,以此类推,创建java对象,最先执行的总是j.l.O的构造方法
class Base{
protected double size;
public Base(){
size=0; System.out.println(“Base类无参构造”);
}
public Base(double s){
size=s;System.out.println(“Base类有参构造”);
}
}
public class Sub extends Base{
private String color;
public Sub(){
color=“blue”;System.out.println(“Sub类无参构造”);
}
public Sub(String c){
color=c;System.out.println(“Sub类有参构造”);
}
public static void main(String[] args){
Sub s1=new Sub(); Sub s2=new Sub(“red”);
}
}
Base类无参构造
Sub类无参构造
Base类无参构造
Sub类有参构造
class Creature(){
public Creature(){
System.out.println("Creature无参的构造函数");
}
}
class Animal extends Creature{
public Animal(String name){
System.out.println("Animal带一个参数的构造方法,该动物的name为"+name);
}
public Animal(String name , int age){
this(name);
System.out.println("Animal带2个参数的构造方法,该age为"+age);
}
}
public class Wolf extends Animal{
publioc Wolf(){
super("土狼",3);
public Animal(String name){
this(name);
System.out.println("Wolf"无参构造方法);
}
public static void main(String[] args){
new Wolf();
}
}
上到下运行,如果某个父类通过this调用同类中的构,就会依次执行此父类的多个构。