Java 多态

本文讲述了Java编程中继承的概念,包括final关键字的使用,如修饰类、属性和方法的含义。讨论了static修饰的属性和方法,强调它们属于类而不是对象,并且可以被所有类的实例共享。此外,文章还介绍了多态的概念,以及向上转型和向下转型在面向对象编程中的应用。
摘要由CSDN通过智能技术生成

零、复习昨日

继承好处:减少冗余、提高复用、多态的前提
继承后:子类可以使用父类非私有属性和方法,父类不能向下使用子类任何的成员
super:代表父类的引用,可以使用父类方法属性和方法
重写:父类的方法不适用于子类,子类需要重写改变以适用自己
重写的要求:访问修饰符、返回值类型、方法名、参数列表全部一样
特殊的:访问修饰的权限 子类 >= 父类
对象创建的过程:
只有一个类:1.开辟空间;2.属性初始化;3.执行构造方法内的代码;4.地址值赋值给对象。
子类创建对象:先执行父类的属性初始化,再执行父类构造方法内的代码;再对子类对象初始化,子类构造方法内代码执行

一、final

final:最终;可以修饰类、属性、方法;
final修饰类,类不能被继承(太监类...)
final修饰属性及变量,变量不再变化,为常量;常量不能被重新赋值;常量命名全部大写(A , ID_CARD……)
final修饰方法,方法不能被重写
public class TestFinal {
    // a成为常量,不能再变化
    // 一般来说,常量命名全部大写
    final int A = 1;
    final String ID_CARD = "11111111";
    int c = 1;

    public void test(){
        // A = 2;          // 常量不能被重写赋值
        c = 2;
    }
}
// 类不能继承
/*final*/ class Super{

    // 方法不能重写
    final void m1(){}
}
class Sub extends Super{
    // @Override
    // void m1() {
    //
    // }
}

二、static

2.1 static语法特点

static:静态的;
静态修饰属性和方法
一旦修饰属性和方法,那么属性和方法就会变成==类属性、类方法==
被static修饰的属性和方法随着类加载而初始化
且被static修饰的属性和方法在内存中只有一份,被所有该类共享
静态修饰的属性和方法==不会随着创建对象进堆中==,就存在于静态域中

以前每次创建对象,每个对象都有属于自己的属性,这些属性叫对象属性。现在static修饰了属性和方法后,这属性和方法不再属于某个对象,而是属于类,称为类属性类方法

public class Student {

    private String name;
    private int age;
    static String school;
    // set get...
    // 打印学生信息
    public void printInfo(){
        System.out.println("姓名:"+name+",年龄:"+age+",学校:"+school );
    }
}

public class TestStatic {

    public static void main(String[] args) {
        Student s1 = new Student("亚瑟",18,"德玛西亚学院");
        s1.printInfo();

        Student s2 = new Student("安其拉",9);
        s2.printInfo();


        Student s3 = new Student("李白",29);
        s3.printInfo();
        // 发现s2,s3虽然没有赋值school,但是输出有值
    }
}

2.2 语法应用

静态修饰的属性和方法建议直接通过类名调用;

因为:静态的属性和方法随着类加载就已经出现在内存中,并初始化成功,意味着可以使用了,就没有必要再通过创建对象后使用对象去调用,这样反而耽误时间和空间!!

练习时将测试类定义成static,方便使用

static方法只能调用静态方法和静态属性

因为:静态修饰的属性和方法随着类加载就已经出现在内存中,并初始化成功,而对象属性对象方法(非静态属性和非静态方法)是需要创建对象才会出现。即:有静态属性和静态方法时,那些没静态的属性和方法还没出现

总结:静态只能调用静态

非静态方法能调用静态方法和静态属性
静态方法内不能使用this
public class TestStatic {
    public static void main(String[] args) {
        // 类名调用静态属性
        Student.school = "啦啦啦啦";
        // 类名调用静态方法
        Student.study();

        Student s1 = new Student("亚瑟",18);
        // 不建议通过对象调用静态属性和方法
        s1.school = "zzzz";
        s1.study();

        s1.printInfo();

        Student s2 = new Student("安其拉",9);
        s2.printInfo();


        Student s3 = new Student("李白",29);
        s3.printInfo();

    }

    public static void m1(){
        // 静态内不能使用this
        //System.out.println(this );
        
        // 静态不能调用非静态
        //m2();
    }

    public void m2(){
        System.out.println(this );
        // 非静态可以调用静态
        m1();
    }
}

2.3 总结

什么时候需要使用static?

  1. main方法方便调用使用其他方法时,将其他方法定义成静态

  1. 但有些数据需要被共享时,就需要使用static.例如:火车票剩余票数:需要被所有售票窗口共享

三、多态

多态
生活中的多态:蝌蚪
程序中的多态:某个方法的多个形态,同一个方法执行时会出现不同的效果
==多态形成的前提条件==
有继承关系(或者实现接口)
子类重写父类方法
父类引用指向子类对象,也叫向上转型

==编译看父类,运行看子类==父类引用只能调用父类内有的方法,不能调用子类的方法

package com.qf.poly;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
public class TestPoly {
    public static void main(String[] args) {

        // 父类引用指向子类对象(向上转型)
        Animal animal = new Dog();
        /**
         * 编译看父类,运行看子类
         * 父类引用只能调用父类内有的方法,不能调用子类的方法
         */
        //animal.eat();

        Animal animal2 = new Cat();
        //animal2.eat();

        // 饲养员开始喂
        // Dog dog = new Dog( );
        // feedDog(dog);
        // feedCat(new Cat( ));

        feedAnimal(new Dog());
        feedAnimal(new Cat());
        feedAnimal(new Tiger());
    }

    /**
     * 饲养员喂动物,让它们吃
     * 但是动物园每新来一个动物都要重新创建一个方法,很麻烦
     */
    public static void feedDog(Dog dog) {
        dog.eat();
    }

    public static void feedCat(Cat cat) {
        cat.eat();
    }

    /**
     * 使用多态将方法改造,以达到扩展性好
     */
    public static void feedAnimal(Animal animal) {
        animal.eat();
    }
}

四、向上转型&向下转型

向上转型:父类引用指向子类对象,子类对象向上转型成了父类
向下转型:父类引用向下转型成为子类默认不允许,可以通过强制类型转换来完成 Dog dog = (Dog) animal;

什么时候需要向下转型?但需要调用子类特有的方法时,就需要将父类引用向下转型成子类对象,才可以使用子类特有的方法!

    /**
     * 使用多态将方法改造,以达到扩展性好
     */
    public static void feedAnimal(Animal animal) {
        animal.eat();
        // 判断animal内部是什么类型的对象
        if (animal instanceof Dog) {
            Dog dog = (Dog) animal;
            dog.watchHome();
        } else if (animal instanceof Cat) {
            Cat cat = (Cat) animal;
            cat.catchMouse();
        }
    }

五、多态应用

package com.qf0215;/**
 * @escription:
 * @author:灰总
 * @data:
 *
 */

class Shape {
    public double area(){
        return 0.0;
    }
    public double girth(){
        return 0.0;
    }
}

class Circle extends Shape {
    private double r;

    public Circle(){}
    public Circle(double r) {
        this.r = r;
    }

  public void setR(double r){
        this.r = r;
    }
    public double getR(){
        return r;
  }

    @Override
    public double area() {
        return 3.14*r*r;
  }

    @Override
    public double girth() {
        return 2*3.14*r;
  }
}

class Rect extends Shape {
    private double length;
    private double width ;

    public Rect(){}
    public Rect(double length, double width) {
        this.length = length;
        this.width = width;
    }

  public void setLength(double length) {
        this.length = length;
    }
    public double getLength() {
        return length;
    }

    public void setWidth(double width) {
        this.width = width;
    }
    public double getWidth() {
        return width;
    }

    @Override
    public double area() {
        return length * width;
    }

    @Override
    public double girth() {
        return 2*(length + width);
    }
}

class Square extends Rect {
    private double l;

    public Square(){}
    public Square(double l) {
        this.l = l;
    }

    public double getL() {
        return l;
    }
    public void setL(double l) {
        this.l = l;
    }

    @Override
    public double area() {
        return l*l;
    }

    @Override
    public double girth() {
        return 4*l;
    }
}

public class TestShape{
    public static void main(String[] args) {

        // 创建一个形状数组
        Shape[] shapes = new Shape[3];

        // 相当于Shaper shape = new Circle();
        // 这就是向上转型
        shapes[0] = new Circle(2);
        shapes[1] = new Rect(5,4);
        shapes[2] = new Square(4);

        for (int i = 0; i < 3; i++) {
            // 从数组取出的是父类引用,相对于是Shape shape,
            // 但是运行的时候看子类的效果
            System.out.println(shapes[i].area());
            System.out.println(shapes[i].girth());
        }
    }
}
设计一个合理的程序:有一个灯泡(Bulb)类.灯泡有发光的方法,他有两个子类,分别是红灯泡和绿灯泡;
还有一个台灯(TableLamp)类,他有一个开灯的方法,实现开红灯,红灯亮,发红光,开绿灯,绿灯亮,发绿光;
public class Bulb {
    public void light() {
        System.out.println("灯泡发光" );
    }
}
class GreenBulb extends Bulb {
    @Override
    public void light() {
        System.out.println("绿灯泡,发绿光" );
    }
}
class RedBulb extends Bulb{
    @Override
    public void light() {
        System.out.println("红灯泡,发红光" );
    }
}
 class TableLamp {
    public void open(Bulb bulb) {
        bulb.light();
    }
    public static void main(String[] args) {
        // 买台灯
        TableLamp tableLamp = new TableLamp( );

        // 买不同颜色的灯泡
        RedBulb redBulb = new RedBulb( );
        GreenBulb greenBulb = new GreenBulb( );
        PinkBulb pinkBulb = new PinkBulb( );

        // 装灯,开灯
        tableLamp.open(redBulb);
        tableLamp.open(greenBulb);
        tableLamp.open(pinkBulb);
    }
}
总结:多态到底怎么用?什么时候用?
大部分的多态使用场景就是将 方法的参数列表设计成父类类型,调用方法时传入子类类型,运行得到子类的效果
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值