java学习之构造,继承,多态

java学习之构造,继承,多态

  • (萌新每日记录,求指点)内容均参考自b站动力节点疯狂java讲义.

一、构造方法:

1、构造方法语法结构:
【修饰符列表】 构造方法名 (形式参数列表){
构造方法体;
}
2、回顾普通方法的语法结构:
【修饰符列表】 返回值类型 方法名(形式参数列表){
方法体;
}
3、构造方法的“返回值类型”,不需要指定,也不需要写void。
4、构造方法的方法名必须和类名保持一致。
5、构造方法的作用:
(1)通过构造方法创建对象
(2)创建对象的同时,初始化实例变量的内存空间
看代码:

public class Support  {
    public String name;
    public int count;
    public Support(String name,int count)
    {
        this.name=name;
        this.count=count;
    }
    public static void main(String[] args) {
        Support tc=new Support("java学习",1000);
        System.out.println(tc.name);
        System.out.println(tc.count);
    }
}

输出结果会是:java学习和1000;
6、如何调用构造方法?
对于普通方法:
—当方法修饰符中有static的时候:类名.方法名(实参列表)
没有static时候:引用.方法名(实参列表)
—构造方法:
new 构造方法名(实参列表)
构造方法执行结束后程序会自动会返回构造方法所在类的类型

二、继承(及方法覆盖)

继承的基本作用是代码复用,但最重要的作用是有了继承才有了以后方法的覆盖和多态机制。
1、基础语法:
语法格式:
【修饰符列表】 class 类名 extends 父类名{
类体=属性+方法
}
例子:

//父类
public class Fruit
{
   public double weight;
   public void info()
   {
   System.out.println("水果,重"+weight+"g!");
   } 
}
//子类
public class Apple extends Fruit
{
    public static void main(String[] args)
    {
    Apple a=new Apple();
    a.weight=56;
    a.info();
    }
}

2、java继承只支持单继承,一个类不能继承很多类(可以间接继承:A extendsB,B extends C,则A间接继承C),在c++中支持多继承。
继承中的术语:
B类继承A类时:A类称为父类,基类,超类,superclass
B类称为子类,派生类,subclass
3、子类继承父类的哪些数据?
—私有的不支持继承
—构造方法不支持继承,其他数据都可以被继承。
4、java中的类没有显示继承任何类,该类默认继承javase库中的java.lang.Object类。

5、重写父类的方法:
(引用疯狂java的例子)鸵鸟是鸟的子类,但其明显不满足鸟类飞翔的特征,需要重写方法。

//Bird父类
public class Bird {
    //fly方法
    public void fly()
    {
        System.out.println("我会飞");
    }
}
//Ostrich子类(重写了fly方法)
public class Ostrich extends Bird{
    //重写Bird类的fly方法
    public void fly()
    {
        System.out.println("我不会飞");
    }

    public static void main(String[] args) {
        Ostrich os=new Ostrich();
        os.fly();
    }
}

这时os.fly执行的便是执行Ostrich类中重写后的fly方法。这种子类包含与父类同名方法的现象被称为方法重写,也称为方法覆盖,方法重写应遵循“两大两小一大”规则(不知道的搜搜吧,我太懒了,呜呜~~)
注意:覆盖方法必须都同为类方法或实例方法;
有private访问权限的方法对其子类隐藏,不具备方法覆盖条件,构造方法也不能覆盖(连继承都继承不了的肯定不能覆盖);
静态方法不存在覆盖;
覆盖只针对方法,不谈属性;
访问权限不能更低可以更高。
子类覆盖父类方法后,子类对象将无法访问父类中被覆盖的方法,但可以在子类方法中调用父类中被覆盖的方法,这时就可以使用 super(被覆盖的是实例方法)或父类类名(被覆盖的是类方法)作为调用者来调用父类中被覆盖的方法。

super限定

super关键字用于限定该对象调用他从父类继承得到的实例变量或方法。
同this一样,super关键字是不能出现在static修饰的方法中的。
先举个例子:

在上文中Ostrich类继承了Bird类并重写了Bird类中的fly方法,如果想要调用父类被覆盖的fly方法则可以在Ostrich类中加上如下代码:

super.fly();

这样就可以通过super调用父类的被覆盖方法。
super还有个作用是调用父类构造器
看例子:

class Base
{
   public double size;
   public String name;
   public Base(double size,String name)
   {
    this.name=name;
    this.size=size;
   } 
}
public class Sub extends Base
{
    public String color;
    public Sub(double size,String name,String color)
    {
    //通过super调用来调用父类构造器的初始化过程
    super(size,name);//必须在第一行
    this.color=color;
    }
    public static void main(String[] args)
    {
    Sub s=new Sub(5.6,"测试对象","红色");
    System.out.println(s.size+"--"+s.name+"--"+s.color);
    }
}

不管是否使用super 调用来执行父类构造器的初始化代码,子类构造器总会调用父类构造器一次,子类构造器调用父类构造器分如下几种情况:

➢子类构造器执行体的第一行使用 super显式调用父类构造器,系统将根据super调用里传入的实参列表调用父类对应的构造器。

➢子类构造器执行体的第一行 代码使用this显式调用本类中重载的构造器,系统将根据this调用里传入的实参列表调用本类中的另一个构造器。执行本类中另一个构造器时即会调用父类构造器。

➢子类构造器执行体中既没有super调用,也没有this调用,系统将会在执行子类构造器之前,隐式调用父类无参数的构造器。

不管上面哪种情况,当调用子类构造器来初始化子类对象时,父类构造器总会在子类构造器之前执行;不仅如此,执行父类构造器时,系统会再次上溯执行其父类构造器…依此类推,创建任何Java对象,最先执行的总是javalangQbject类的构造器。

三、多态

1,首先定义三个类:Animal,Cat,Bird, Cat继承Animal,Bird继承Animal,Cat和Bird间没有任何继承关系。
其中Cat,Bird和Animal类中均有move()方法,Cat类具有catchMouse()方法,
多态中涉及的几个概念:
*对象的实例变量不存在多态。
*向上转型(upcasting)-子类型转换为父类型(自动类型转换),即可以将一个子类对象赋给一个父类引用变量。
*向下转型(downcasting)-父类型转换为子类型(强制类型转换【需要加强制类型转换符】)
*无论是向上转型还是向下转型,两种类型间必须有继承关系

2、使用多态语法机制:
Animal与Cat间有继承关系,Animal为父类,Cat为子类,有下列代码:

Animal a2=new Cat();//子类型转换为父类型(向上转型)

*java程序永远分为编译阶段运行阶段,先分析编译阶段后分析运行阶段,编译无法通过,程序就无法运行。

 a2.move();

编译阶段检查a2的数据类型为Animal,在这个类中有move()方法,所以编译通过(静态绑定,编译阶段绑定)。静态绑定成功后才有后续运行。
运行阶段,在堆内存中真实创建的对象是Cat对象,则一定会调用Cat对象1的move()方法。发生了动态绑定,运行阶段绑定。

a2.catchMouse();

这段代码在编译时会引发错误,因为它编译时的类型为Animal,其中没有catchMouse()方法,自然无法调用。
*父类型引用指向子类型对象这种机制导致程序存在编译阶段绑定和运行阶段绑定两种不同的形态/状态,这种机制可以成为一种多态语法机制。

引用变量的强制类型转换

在上述例子中a2为Animal类型,如果有这样一段代码:

a2.catchMouse();//Animal类中没有catchMouse()方法

刚才已经说过,如果直接编译是会报错的,但如果我们进行强制类型转换为Cat类,就可以通过了。
用法:(type)variable,这样可以把variable变量转换成一个type类型的变量。
*什么时候需要用到强制类型转换(向下转型)?
当调用的方法是子类中特有的,在父类当中不存在。
类型转换异常

Animal a3=new Bird();
Cat a3=(Cat)a3;

这段代码可以编译通过,但在运行阶段会出现异常,因为JVM堆内存中真实存在的是Bird类,Bird对象无法转换为Cat对象,因为其不存在继承关系,即出现ClassCastException异常。为了避免这种异常便出现了instanceof运算符。

instanceof运算符

用法:(引用 instanceof 数据类型名)
执行结果返回布尔类型(ture/false)。
作用:用于判断前面的对象是否是后面的类,或者其子类,实现类的实例,是则返回ture,否则返回false.
例子:

if(a3 instanceof Cat){
   Cat c3=(Cat)a3;
   c3.catchmouse();
}else if(a3 instanceof Bird){
    Bird b2=(Bird)a3;
    b2.fly();
}

四、最后

再见啦妈妈今晚我就要远航~~~~~~~~;

你可能感兴趣的:(多态,java,继承)