小白学Java代码:面向对象(多态)

编写车Vehicle的父类,属性:车牌号、品牌
     方法:计算总租金
           public int getSumRent(int days){
                return 100;
           }
package com.jian.demo1;

public class Vehicle {
    //编写实例变量
    String id;
    String brand;

    public Vehicle() {
    }

    public Vehicle(String id, String brand) {
        this.id = id;
        this.brand = brand;
    }
    //方法:计算总租金
    public int getSumRent(int days){
        //注意:不同车的总租金不一样,也就是需要在子类中重写,因此父类的总租金方法体可以编写任意一个int类型的值返回
        return 0;
    }

    public void print(){
        System.out.println("OK");
    }
}
编写大巴车子类 继承车的父类
  独有属性:座位
  座位数<16,400元    座位数>=16,600元
  重写父类的总租金方法
package com.jian.demo1;

public class Bus extends Vehicle {
    //编写独有实例变量
    int seat;

    public Bus() {
    }

    public Bus(String id, String brand, int seat) {
        super(id, brand);
        this.seat = seat;
    }

    @Override
    public int getSumRent(int days) {
        /*
            总租金 = 日租金 * 租的总天数
            但是日租金要根据实例变量座位数进行判断得到
         */
        if(this.seat < 16){
            return 400 * days;
        }
        return 600 * days;
    }
}
编写小轿车子类 继承车的父类
  独有的属性:车型(两厢、三厢、越野)
  两厢300元、三厢350元、越野500元
  重写父类的总租金方法
package com.jian.demo1;

public class Car extends Vehicle {
    //编写独有实例变量
    String type;

    public Car() {
    }

    public Car(String id, String brand, String type) {
        super(id, brand);
        this.type = type;
    }

    @Override
    public int getSumRent(int days) {
        /*
            总租金 = 日租金 * 租的总的天数
            但是日租金要根据实例变量车型判断得到
         */
        if("两厢".equals(this.type)){
            return 300 * days;
        }else if("三厢".equals(this.type)){
            return 350 * days;
        }else{
            return 500 * days;
        }
    }
}

编写测试类

package com.jian.demo1;

public class Test {
    public static void main(String[] args) {
        /*
            多态的语法格式:
                父类类型 对象名 = new 子类();
            注意:当构成多态时,对象名是父类类型,因此只能访问父类中的实例变量和父类的实例方法,但是优先访问子类重写以后的方法
         */
        Vehicle c = new Car(); //构成多态
        System.out.println(c.id);
        System.out.println(c.brand);
//        System.out.println(c.type); //出现编译错误,原因:当前对象名c是父类类型,父类中没有车型实例变量,因此就出现编译错误

        c.print();
        System.out.println("总租金:" + c.getSumRent(1)); //输出500,原因:当构成多态以后,会优先调用当前子类对象中重写以后的方法
    }
}
package com.bjpowernode.demo1;

public class Test2 {
    public static void main(String[] args) {
//        Car c = new Car(); //不报错,但是没有构成多态
        Vehicle v = new Bus(); //构成多态
        System.out.println("总租金:" + v.getSumRent(1)); //400
        v = new Car(); //构成多态
        System.out.println("总租金:" + v.getSumRent(1)); //500
        /*
            通过运行得到:
                1.多态定义:
                  多个对象调用同一个方法,得到多个不同的结果,原因:构成多态后,优先调用子类重写以后的方法
                  多种不同的形态(结果)
                  在现实生活中多态案例,比如:理发师、裁缝、医生.....都使用剪刀,得到不一样的结果                  2.满足多态的条件:
                    子类继承父类
                    必须在子类中重写父类的方法
                    父类类型 对象名 = new 子类();
         */
    }
}
宠物Pet类  方法:吃
package com.jian.demo2;

public class Pet {
    //编写方法:吃
    public void eat(){
        System.out.println("正在吃.......");
    }
}

编写子类

package com.jian.demo2;

public class Dog extends Pet {
    @Override
    public void eat() {
        System.out.println("小狗正在吃狗粮....");
    }
}
package com.jian.demo2;

public class Cat extends Pet {
    @Override
    public void eat() {
        System.out.println("小猫正在吃鱼......");
    }
}
package com.jian.demo2;

public class Bird extends Pet {
    @Override
    public void eat() {
        System.out.println("小鸟正在吃虫子.....");
    }
}
编写主人类    方法:喂养feed猫
package com.jian.demo2;

public class Master { //编写主人类
    //编写方法:喂养feed猫
    /*public void feed(Cat cat){
        cat.eat();
    }
    public void feed(Dog dog){
        dog.eat();
    }*/
    /*
        可是宠物有很多,也就是说有多个具体的宠物,则就需要在主人类中编写多个喂养的方法,但是比较麻烦
        其实以上两个喂养方法中的形参猫和狗都是从宠物继承过来的,因此能否编写主人喂养宠物这一个方法
     */
    public void feed(Pet pet){
        pet.eat();
    }
}

编写测试类

package com.jian.demo2;

public class Test {
    public static void main(String[] args) {
        //创建主人对象
        Master master = new Master();
        //调用主人的喂养方法
        master.feed(new Cat());
        master.feed(new Dog());
        master.feed(new Bird());
    }
}
人类:  属性:姓名,性别、年龄  方法:自我介绍的方法
package com.jian.demo3;

public class Person {
    //编写实例变量
    String name;
    char gender;
    int age;

    public Person() {
    }

    public Person(String name, char gender, int age) {
        this.name = name;
        this.gender = gender;
        this.age = age;
    }
    //编写方法:自我介绍
    public void print(){
        System.out.print("大家好,我叫" + name + ",今年" + age + "岁了,性别是" + gender);
    }
}
学生类 继承 人类  独有属性:学号  独有方法:学习  重写父类的自我介绍
package com.jian.demo3;

public class Student extends Person {
    //独有实例变量:学号
    String id;

    public Student() {
    }

    public Student(String name, char gender, int age, String id) {
        super(name, gender, age);
        this.id = id;
    }
    //编写方法:学习
    public void study(){
        System.out.println("正在学习面向对象......");
    }

    @Override
    public void print() {
        super.print();
        System.out.println(",学号是" + id);
    }
}
教师类 继承人类  独有属性:薪资  独有方法:教学  重写父类的自我介绍方法
package com.jian.demo3;

public class Teacher extends Person {
    //独有薪资
    double salary;

    public Teacher() {
    }

    public Teacher(String name, char gender, int age, double salary) {
        super(name, gender, age);
        this.salary = salary;
    }
    //编写独有方法:教学
    public void teach(){
        System.out.println("正在教面向对象......");
    }

    @Override
    public void print() {
        super.print();
        System.out.println(",薪资是" + this.salary);
    }
}
多态中的向上转型,也叫做自动类型转换
package com.jian.demo3;

public class Test {
    public static void main(String[] args) {
        Person person = new Student(); //构成多态也就是向上转型或者叫做自动类型转换,注意:只能访问父类中的实例变量和父类中的实例方法,但是优先访问子类重写以后的方法
        System.out.println(person.name);
        System.out.println(person.age);
        System.out.println(person.gender);
//        System.out.println(person.id); //出现编译错误,原因:当前对象名是父类类型,不能访问子类独有的,因此就出现编译错误

        person.print();
    }
}
多态中的向下转型也叫做强制类型转换
package com.jian.demo3;

public class Test2 {
    public static void main(String[] args) {
        Person p = new Student(); //构成多态,也叫做向上转换或者叫做自动类型转换
        /*
        实现输出:当是学生对象输出学号,当是教师对象输出薪资
        但是出现编译错误
        原因:当构成多态时,不能直接访问子类独有的实例变量或实例方法
        解决办法:将p强制转为学生类型,然后再访问子类学生中的学号实例变量
         */
//        System.out.println("学号:" + p.id);
//        int a = (int)3.15; //强制类型转换
        Student stu = (Student) p; //强制类型转换,也叫做向下转换,其实由父到子
        System.out.println("学号:" + stu.id);

        /*
            出现运行错误java.lang.ClassCastException类型转换异常
            原因:当前对象名p中存放的是学生对象,也就是说不能随便转为其他子类类型,否则出现类型转换异常
            解决办法:在进行向下转型或者强制类型转换之前先进行判断,如果当前对象名中存放的是该对象,则再进行向下转换或者强制类型转换,则使用instanceof关键字
         */
       /* Teacher t = (Teacher)p;
        System.out.println("薪资:" + t.salary);*/
    }
}
多态中的向下转型也叫做强制类型转换,使用instanceof关键字
package com.jian.demo3;

public class Test3 {
    public static void main(String[] args) {
        Person p = new Student(); //构成多态也就是向上转型也叫做自动类型转换
        //p = new Teacher("张三", '男', 20, 5000);
        /*
            实现功能:
            当前对象名中存放的是学生对象,则输出学生的独有属性学号和学生的独有方法学习
            当前对象名中存放的是教师对象,则输出教师独有属性薪资和调用独有方法教学
            建议:在进行向下转型或者强制类型转换之前,先判断,则使用instanceof关键字
         */
        if(p instanceof Student){
            //表示当前对象名p中存放的是学生对象,则就可以转为学生类型
            /*Student s = (Student)p; //向下转换也叫做强制类型转换
            System.out.println("学号:" + s.id);
            s.study();*/
            //其实上面三条语句也可以编写为如下代码
            System.out.println("学号:" + ((Student) p).id);
            ((Student) p).study();
        }else if(p instanceof Teacher){
            //表示当前对象名p中存放地点是教师对象,则就可以转为教师类型
            Teacher t = (Teacher)p; //向下转换也叫做强制类型转换
            System.out.println("薪资:" + t.salary);
            t.teach();
        }
    }
}
package com.jian.demo3;

public class Test4 {
    public static void main(String[] args) {
        Student stu = new Student(); //没有构成多态,不报错
        /*
        注意:当前对象名stu是学生类型,在访问实例变量或实例方法时,先在学生类中找,如果找不到则再去父类中找
            也就得到结论:如果对象名是子类类型,既可以访问子类中的实例变量和实例方法,也可以访问父类中的实例变量和实例方法
         */
        System.out.println("姓名:" + stu.name);
        System.out.println("学号:" + stu.id);

        stu.print();
        stu.study();

        Person stu2 = new Student(); //构成多态,也就是向上转型或者自动类型转换
        /*
         注意:当前对象名stu2是父类类型,只能访问父类中的实例变量和实例方法,但是优先访问子类重写以后的方法
              如果构成多态,非要访问子类独有的实例变量或实例方法,则必须进行向下转型也叫做强制类型转换
         */
    }
}

修改租车租金测试类

package com.jian.demo4;

import java.util.Scanner;

/**
 * 测试类使用多态完成计算总租金,并且优化代码,调用总租金方法编写在switch外面,建议先判断否则可能会出现空指针异常
 *
 */
public class Test2 {
    public static void main(String[] args) {
        //根据选择不同的车来计算不同车的租金
        //第一步:键盘输入要选择租赁的车
        Scanner input = new Scanner(System.in);
        System.out.println("请选择要租赁的车:(1.Car 2.Bus)");
        int num = input.nextInt();
        //第二步:根据输入num中的值创建对象,并且计算总租金
        Vehicle v = null;
        switch (num){
            case 1: //表示Car
                //创建小轿车对象
                v = new Car(); //构成多态,也叫做向上转型或者叫做自动类型转换
                break;
            case 2: //表示Bus
                //创建大巴车对象
                v = new Bus(); //构成多态,也叫做向上转型或者叫做自动类型转换
                break;
            default:
                System.out.println("输入编号有误!");
        }
        //建议:在调用总租金方法之前,先判断,如果当前对象名v不等于null则在调用总租金方法,否则可能回车空指针异常
        if(v != null){
            System.out.println("总租金:" + v.getSumRent(1)); //优先调用子类重写以后的方法
        }
    }
}
package com.jian.demo4;

import java.util.Scanner;

/**
 * 将根据编号创建对象抽取方法完成
 * 
 */
public class Test3 {
    public static void main(String[] args) {
        //根据选择不同的车来计算不同车的租金
        //第一步:键盘输入要选择租赁的车
        Scanner input = new Scanner(System.in);
        System.out.println("请选择要租赁的车:(1.Car 2.Bus)");
        int num = input.nextInt();
        //第二步:根据输入num中的值创建对象,并且计算总租金
        Vehicle v = getVehicle(num);
        //建议:在调用总租金方法之前,先判断,如果当前对象名v不等于null则在调用总租金方法,否则可能回车空指针异常
        if(v != null){
            System.out.println("总租金:" + v.getSumRent(1)); //优先调用子类重写以后的方法
        }
    }

    public static Vehicle getVehicle(int num) {
        Vehicle v = null;
        switch (num){
            case 1: //表示Car
                //创建小轿车对象
                v = new Car(); //构成多态,也叫做向上转型或者叫做自动类型转换
                break;
            case 2: //表示Bus
                //创建大巴车对象
                v = new Bus(); //构成多态,也叫做向上转型或者叫做自动类型转换
                break;
            default:
                System.out.println("输入编号有误!");
        }
        return v;
    }
}
1.static关键字可以修饰属性
package com.jian.demo5;

/**
 * 1.static关键字可以修饰属性
 *      1.1在类中声明的变量,称为属性也叫做成员变量或者字段field
 *         如果属性(成员变量或者字段)没有使用static关键字修饰,称为实例变量,也就是对象变量
 *         如果属性(成员变量或者字段)使用static关键字修饰,称为静态变量,也就是类的变量
 *      1.2静态变量的特点:
 *          1.2.1当类加载到内存时,则就给静态变量分配空间,一直到程序结束
 *          1.2.2静态变量在方法区中存储
 *          1.2.3静态变量不属于某个对象,而是整个类中的所有对象都可以共享
 *               因此可以使用:类名.静态变量名
 *               也可以使用:对象名.静态变量名
 *               即使对象名的值为null时,也可以访问静态变量,不会出现空指针异常,原因:静态变量当类加载内存时就在方法区中存在,一直到程序结束
 *          1.2.4类优先于对象,也就是说类的生命周期比较长
 *     1.3静态变量使用场景:
 *          当多个对象中的某个属性值都一样时,则就可以编写为静态变量,原因:在方法区中只存放一次,也就是说节省空间
 * 
 */
public class MyClass {
    int x; //实例变量也就是对象变量
    static int y; //静态变量也叫做类的变量

    static String address = "北京市";
}
package com.jian.demo5;

public class Test {
    public static void main(String[] args) {
        /*
        注意:1.当使用MyClass类,则就将MyClass.class字节码文件加载到内存,同时在方法区中给静态变量y分配空间,并且y的值为0
        注意:2.因此使用类名可以访问静态变量名
         */
        System.out.println(MyClass.y); //0
//        System.out.println(MyClass.x); //出现编译错误,原因:当前x是实例变量,也就是说目前还没有创建对象,实例变量x还不存在

        //注意:目前还没有创建对象,也就是说对象以及实例变量和实例方法都不存在
        /*
          假如创建MyClass对象
          当执行new运算符,则表示在堆内存中创建一个对象,并且开辟一块空间进行存储,并且该对象中存放实例变量x,x的值为默认值0
          则就可以使用:对象名.实例变量名
          也可以使用对象名.静态变量名  原因:静态变量一直到程序结束,也就是说如果程序还没有结束,则静态变量就一直存在
         */
        MyClass m = new MyClass();
        System.out.println(m.x);  //0
        System.out.println(m.y);  //0

        /*
         假如对象使用完毕,则就变为垃圾回收
         同时该对象中的实例变量也随之释放,也就是实例变量x不存在
         也就是说,如果对象名的值为null时,则就不能访问对象中的实例变量或实例方法,否则出现空指针异常
         */
        m = null;
//        System.out.println("m.x = " + m.x);
        System.out.println("m.y = " + m.y);  //0

    }
}

2.static关键字可以修饰方法

package com.jian.demo6;

/**
 * 2.static关键字可以修饰方法
 *      2.1如果使用static关键字修饰方法,称为静态方法也叫做类的方法
 *         如果没有使用static关键字修饰方法,称为实例方法也叫做对象的方法、非静态方法
 *      2.2静态方法中可以使用静态变量和静态方法
 *         实例方法中可以使用静态变量和静态方法,还可以使用实例变量和实例方法
 *         原因:类优先于对象
 *      2.3其实main方法也是静态方法
 *      2.4静态方法使用的场景:
 *          1.一般编写工具类中的工具方法时,该方法编写为静态方法
 *            比如:Math.pow(2,3)
 *          2.一般方法体中没有使用到实例变量和实例方法时,则就可以编写为静态方法
 * 
 */
public class MyClass {
    int x; //实例变量
    static int y; //静态变量
    //编写实例方法
    public void print(){
        y = 11;
        show();

        x = 22;
        print2();
    }
    public void print2(){

    }
    //编写静态方法
    public static void show(){

    }
    public static void show2(){
        y = 100;
        show();
        /*x = 200; //出现编译错误,原因:x是实例变量
        print(); //出现编译错误,原因:print是实例变量*/
    }
}
package com.jian.demo6;

public class Test {
    public static void main(String[] args) {
        Test.print();
        //上面一条语句也可以编写为如下
        print(); //注意:同一个类中的静态方法可以直接访问,默认有当前类的类名.
        //其实还可以编写为:
        /*Test t = new Test();
        t.print(); //静态方法一般使用类名.使用更多*/
        //上面两条语句也可以编写为
        new Test().print();
    }

    private static void print() {
        for(int i = 1;i <= 5;i++){
            System.out.println(i);
        }
    }
}
3.static关键字可以修饰代码块
package com.jian.demo7;

/**
 * 3.static关键字可以修饰代码块
 *      3.1使用static关键字修饰的代码块,称为静态代码块
 *      3.2静态代码块语法格式
 *          static{
 *
 *          }
 *      3.3静态代码块的作用
 *          完成对静态变量赋值
 *      3.4静态代码块如何执行?
 *          当类加载到内存时执行静态代码块,并且只执行一次
 * 
 */
public class MyClass {
    int x; //实例变量
    static int y = 100; //静态变量
    static int z; //静态变量

    //静态代码块
    static {
        z = 200;
        System.out.println("执行了静态代码块......");
    }

    //构造方法:完成对实例变量赋值
    public MyClass() {
        System.out.println("执行了无参构造方法.....");
    }

    public MyClass(int x) {
        this.x = x;
        System.out.println("执行了带一个参数的构造方法.....");
    }
}
package com.jian.demo7;

public class Test {
    public static void main(String[] args) {
        /*
            创建MyClass对象执行过程分析:
                1.先将MyClass.class字节码文件加载到内存中
                2.然后在方法区中开辟空间存储静态变量y和z,并且y的值为100,z的值为默认值0
                3.然后再执行静态代码块,完成对静态变量z赋值,z = 200
                4.执行new运算符,表示创建一个对象,并且在堆内存中开辟一块空间存储一个对象,并且该对象中存放一个实例变量x,x的值为默认值0
                5.同时执行相匹配的构造方法,也就是执行带一个参数的构造方法,完成对实例变量x赋值,x = 123
                6.将对象的内存地址赋给左侧的对象名m,也就是m中存放的是地址
         */
        MyClass m = new MyClass(123);
        m = new MyClass();

        MyClass m2 = new MyClass();
    }
}
4.static关键字可以修饰内部类
package com.jian.demo8;

/**
 * 4.static关键字可以修饰内部类
 *      4.1 什么是内部类?
 *          在一个类中再编写一个类,里面的这个类称为内部类,也叫做嵌套类或者叫做内置类
 *      4.2 一般什么时候定义内部类?
 *          一般内部类是对外部类提供服务的,如果还想对其他外部类提供服务,则不建议编写为内部类
 *      4.3 当内部类前面添加static关键字,称为静态内部类
 * 
 */
public class MyClass { //外部类
    //编写实例方法
    public void print(){
        Inner i = new Inner();
    }
    class Inner{ //内部类,一般在外部类的实例方法中使用

    }

    //编写静态方法
    public static void print2(){
        Inner2 i2 = new Inner2();
    }
    static class Inner2{ //静态内部类,一般在外部类的静态方法中使用

    }
}
5.static关键字可以实现静态导入
package com.jian.demo9;

/**
 * 5.static关键字可以实现静态导入
 *
 * 
 */
public class MyClass {
    static int y = 100; //静态变量
}
package com.bjpowernode.demo9;

import static com.bjpowernode.demo9.MyClass.y;

public class Test {
    public static void main(String[] args) {
        //注意:如果在一个类中想直接使用其他类中的静态变量,则必须实现静态导入
        System.out.println(y); //100
    }
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值