Java_笔记_多态_包_final_权限修饰符_代码块

封装:对象代表什么,就得封装对应的数据,并提供数据对应的行为。

一、多态:对象的多种形态。同类型的对象,表现出的不同形态。

1.多态的表现形式:父类类型 对象名称 = 子类对象;
学生形态 对象
Student s = new Student( );
人的形态 对象
Person p = new Student( );

2.多态的前提:
1)有继承/实现关系。
2)有父类引用指向子类对象。Fu f = new Zi( );
3)有方法的重写。

3.多态的优势:
1)在多态形式下,右边对象可以实现解耦合,便于扩展和维护。
Person p= new Student( );
p.work( ); //业务逻辑发生改变时,后续代码无需修改。
2)★定义方法的时候,使用父类型作为参数,可以接收所有子类对象,体现多态的扩展性与便利。

4.多态的弊端:不能调用子类的特有功能。
1)解决方法:变回子类类型。如果转成其他类类型,会报错。
2)引用数据类型的类型转换,有2种:自动类型转换;强制类型转换。
Person p = new Student(); //自动类型转换
Student s = (Student) p; //强制类型转换
3)强制类型转换,可以转换成真正的子类类型,从而调用子类独有功能。
转换类型与真实对象类型不一致会报错。
转换的时候用instanceof关键字进行判断。
4)代码:

//多态弊端
public class Test {
    public static void main(String[] args) {
        //创建对象
        Animal a = new Dog();
        //编译看左边,运行看右边
        a.eat();

        //多态的弊端
        //不能调用子类的特有功能
        //当调用成员方法的时候,编译看左边,运行看右边
        //在编译的时候会先检查左边的父类中有没有这个方法,如果没有直接报错
        //a.housekeeping();
        //多态弊端解决方法:把调用者a再变回子类类型
        /*int b = 10;
        byte c = (byte) b;*/
        Dog d = (Dog) a;
        d.housekeeping();
        //细节:转换时候不能转换成随意类型,否则报错
        /*Cat c = (Cat) a;
        c.catchMouse();*/

        //实际开发中需要先判断类型是否可以转换
        /*if (a 是不是 狗){
            Dog d = (Dog) a;
        }else if (a 是不是 猫){
            Cat c = (Cat) a;
        }*/

        /*if (a instanceof Dog) {
            Dog dog = (Dog) a;
            dog.housekeeping();
        } else if (a instanceof Cat) {
            Cat cat = (Cat) a;
            cat.catchMouse();
        } else {
            System.out.println("没有这个类型,无法转换");
        }*/

        //★★★JDK14新特性
        //先判断a是否为Dog类型,如果是则强转成Dog类型,转换后变量名为dog
        //如果a不是Dog类型,结果直接为false
        if (a instanceof Dog dog) {
            dog.housekeeping();
        } else if (a instanceof Cat cat) {
            cat.catchMouse();
        } else {
            System.out.println("没有这个类型,无法转换");
        }
    }
}

class Animal {
    public void eat() {
        System.out.println("动物在吃东西");
    }
}

class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }

    public void housekeeping() {
        System.out.println("狗在看家");
    }

}

class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃小鱼干");
    }

    public void catchMouse() {
        System.out.println("猫在抓老鼠");
    }
}

5.多态的应用场景:
1)根据传递对象的不同,调用不同的show方法。
2)代码:

public class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    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 void show() {
        System.out.println(name + "," + age);
    }
}
public class Administrator extends Person {
    @Override
    public void show() {
        System.out.println("管理员的信息为" + getName() + "," + getAge());
    }
}
public class Student extends Person {
    @Override
    public void show() {
        System.out.println("学生的信息为" + getName() + "," + getAge());
    }
}

public class Teacher extends Person {
    @Override
    public void show() {
        System.out.println("老师的信息为" + getName() + "," + getAge());
    }
}

public class Test {
    public static void main(String[] args) {
        //创建三个对象,并调用register方法
        Student s = new Student();
        s.setName("皓恒");
        s.setAge(20);

        Teacher t = new Teacher();
        t.setName("瑞胤");
        t.setAge(30);

        Administrator admin = new Administrator();
        admin.setName("管理员");
        admin.setAge(35);

        register(s);//学生的信息为皓恒,20
        register(t);//老师的信息为瑞胤,30
        register(admin);//管理员的信息为管理员,35
    }

    //这个方法既能接收老师,又能接收学生,还能接收管理员
    //只能把参数写成这三个类型的父类
    public static void register(Person p) {
        p.show();
    }
}

6.多态调用成员的特点:
1)变量调用:编译看左边,运行也看左边。
2)方法调用:编译看左边,运行看右边。
3)代码:

public class Test {
    public static void main(String[] args) {
        //多态方式创建对象
        //Fu f = new Zi();
        Animal a = new Dog();
        //调用成员变量:编译看左边,运行也看左边
        //编译看左边:javac编译代码的时候,会看左边的父类中有没有这个变量,如果有编译成功,否则编译失败
        //运行也看左边:java运行代码的时候,实际获取的就是左边父类中成员变量的值
        //理解:用a去调用变量和方法,a是Animal类型,默认都会从Animal这个类去找
        //成员变量:在子类的对象中,会把父类的成员变量也继承下来
        System.out.println(a.name);//动物

        //调用成员方法
        //编译看左边:javac编译代码的时候,会看左边的父类中有没有这个方法,如果有编译成功,否则编译失败
        //运行看右边:java运行代码的时候,实际上运行的是子类中的方法
        //成员方法:如果子类对方法进行了重写,在虚方法表里会把父类的方法进行覆盖
        a.show();//Dog --- show方法
    }
}

class Animal {
    String name = "动物";

    public void show() {
        System.out.println("Animal --- show方法");
    }
}

class Dog extends Animal {
    String name = "狗";

    @Override
    public void show() {
        System.out.println("Dog --- show方法");
    }
}

class Cat extends Animal {
    String name = "猫";

    @Override
    public void show() {
        System.out.println("Cat --- show方法");
    }
}

7.多态的综合练习

public class Animal {
    /*属性:
    年龄,颜色
    行为:
    eat(String something)(something表示吃的东西)*/
    private int age;
    private String color;

    public Animal() {
    }

    public Animal(int age, String color) {
        this.age = age;
        this.color = color;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public void eat(String something) {
        System.out.println("动物在吃" + something);
    }
}

public class Cat extends Animal {
    public Cat() {
    }

    public Cat(int age, String color) {
        super(age, color);
    }
    /*行为:
    eat(String something)方法(something表示吃的东西)
    逮老鼠catchMouse方法(无参数)*/

    @Override
    public void eat(String something) {
        System.out.println(getColor() + getAge() + "岁的猫狼吞虎咽" + something);
    }

    public void catchMouse() {
        System.out.println("猫抓老鼠");
    }
}
public class Dog extends Animal {
    /*1.定义狗类
    行为:
    eat(String something)(something表示吃的东西)
    看家housekeeping方法(无参数)*/

    //空参构造
    //带全部参数的构造

    public Dog() {
    }

    public Dog(int age, String color) {
        super(age, color);
    }
    /*行为:
    eat(String something)(something表示吃的东西)
    看家housekeeping方法(无参数)*/

    @Override
    public void eat(String something) {
        System.out.println(getAge() + "岁" + getColor() + "的伯恩山犬懒洋洋地躺在靠椅上吃" + something);
    }

    public void housekeeping() {
        System.out.println("狗在看家");
    }
}

public class Person {
    /*属性:
    姓名,年龄
    行为:
    keepPet(Dog dog,String something)方法
    功能:喂养宠物狗,something表示喂养的东西
    行为:
    keepPet(Cat cat,String something)方法
    功能:喂养宠物猫,something表示喂养的东西
    生成空参有参构造,set和get方法

    定义测试类(完成以下打印效果):
    keepPet(Dog dog,String something)方法打印内容如下:
    年龄为30岁的饲养员养了一只黑色的3岁的伯恩山犬 // 饲养员的行为
    3岁黑色的伯恩山犬懒洋洋地躺在靠椅上吃牛肉 //狗的行为
    keepPet(Cat cat,String something)方法打印内容如下:
    年龄为35岁的铲屎官养了一只棕色的6岁的猫
    棕色6岁的猫狼吞虎咽三文鱼罐头*/
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    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;
    }

    /*keepPet(Dog dog,String something)方法打印内容如下:
    年龄为30岁的饲养员养了一只黑色的3岁的伯恩山犬 // 饲养员的行为
    3岁黑色的伯恩山犬懒洋洋地躺在靠椅上吃牛肉 //狗的行为
    keepPet(Cat cat,String something)方法打印内容如下:
    年龄为35岁的铲屎官养了一只棕色的6岁的猫
    棕色6岁的猫狼吞虎咽三文鱼罐头*/

    /*//饲养狗
    public void keepPet(Dog dog, String something) {
        System.out.println("年龄为" + getAge() + "岁的" + getName() +
                "养了一只" + dog.getColor() + "的" + dog.getAge() + "岁的伯恩山犬");
        dog.eat(something);
    }

    //饲养猫
    public void keepPet(Cat cat, String something) {
        System.out.println("年龄为" + getAge() + "岁的" + getName() +
                "养了一只" + cat.getColor() + "的" + cat.getAge() + "岁的猫");
        cat.eat(something);
    }*/

    //生成一个方法,能接收所有的动物
    //方法的形参,可以写这些类的父类Animal
    public void keepPet(Animal a, String something) {
        if (a instanceof Dog d) {
            System.out.println("年龄为" + getAge() + "岁的" + getName() +
                    "养了一只" + d.getColor() + "的" + d.getAge() + "岁的伯恩山犬");
            d.eat(something);
        } else if (a instanceof Cat c) {
            System.out.println("年龄为" + getAge() + "岁的" + getName() +
                    "养了一只" + c.getColor() + "的" + c.getAge() + "岁的猫");
            c.eat(something);
        } else {
            System.out.println("没有这种动物");
        }
    }
}

/*根据需求完成代码:
1.定义狗类
属性:
年龄,颜色
行为:
eat(String something)(something表示吃的东西)
看家housekeeping方法(无参数)

2.定义猫类
属性:
年龄,颜色
行为:
eat(String something)方法(something表示吃的东西)
逮老鼠catchMouse方法(无参数)

3.定义Person类//饲养员
属性:
姓名,年龄
行为:
keepPet(Dog dog,String something)方法
功能:喂养宠物狗,something表示喂养的东西
行为:
keepPet(Cat cat,String something)方法
功能:喂养宠物猫,something表示喂养的东西
生成空参有参构造,set和get方法

4.定义测试类(完成以下打印效果):
keepPet(Dog dog,String something)方法打印内容如下:
    年龄为30岁的饲养员养了一只黑色的3岁的伯恩山犬 // 饲养员的行为
    3岁黑色的伯恩山犬懒洋洋地躺在靠椅上吃牛肉 //狗的行为
keepPet(Cat cat,String something)方法打印内容如下:
    年龄为35岁的铲屎官养了一只棕色的6岁的猫
    棕色6岁的猫狼吞虎咽三文鱼罐头

5.思考:
    1.Dog和Cat都是Animal的子类,以上案例中针对不同的动物,定义了不同的keepPet方法,过于繁琐,能否简化,并体会简化后的好处?
    2.Dog和Cat虽然都是Animal的子类,但是都有其特有方法,能否想办法在keepPet中调用特有方法?*/
public class Test {
    public static void main(String[] args) {
        /*//创建对象并调用方法
        Person p1 = new Person("饲养员", 30);
        Dog d = new Dog(3, "黑色");
        p1.keepPet(d, "牛肉");

        Person p2 = new Person("铲屎官", 35);
        Cat c = new Cat(6, "棕色");
        p2.keepPet(c, "三文鱼罐头");*/

        //创建饲养员的对象
        Person p = new Person("饲养员", 30);
        Dog d = new Dog(3, "黑色");
        Cat c = new Cat(6, "棕色");
        p.keepPet(d, "牛肉");
        p.keepPet(c, "三文鱼罐头");
    }
}

二、包

1.作用:
1)包就是文件夹。
2)用来管理各种不同功能的Java类,方便后期代码维护。
2.包名的规则:公司域名反写+包的作用。
需要全部英文小写,见名知意。com.company.domain

package com.company.domain

public class Student{
私有化成员变量
构造方法
成员方法
}
3.全类名/全限定名:包名+类名
com.company.domain.Student
4.使用其他类的规则
1)推演:
使用其他类时,需要使用全类名。

public class Test {
    public static void main(String[] args) {
        com.company.domain.Student s = new com.company.domain.Student();
    }
}
//导包
import com.company.domain.Student;

public class Test {
    public static void main(String[] args) {
        Student s = new Student();
    }
}

2)使用同一个包中的类时,不需要导包。
3)使用java.lang包中的类时,不需要导包。
4)其他情况都需要导包。
5)如果同时使用两个包中的同名类,需要用全类名。

三、final:最终的,不可被改变的。

1.final修饰方法(了解):表明该方法是最终方法,不能被重写。
应用:不想被改变的规则方法。
2.final修饰类(了解):表明该类是最终类,不能被继承。
3.final修饰变量(掌握):叫做常量,只能被赋值一次。
1)常量:实际开发中,常量一般作为系统的配置信息,方便维护,提高可读性。
2)常量的命名规范:
单个单词:全部大写。
多个单词:全部大写,单词之间用下划线隔开。
3)★★★细节:
final修饰的变量是基本数据类型:变量存储的数据值不能发生改变。
final修饰的变量是引用数据类型:变量存储的地址值不能发生改变,对象内部的属性值可以改变。
4)核心:
常量记录的数据是不能发生改变的。
5)字符串是不可变的(private,final)。
6)常量的练习:
将学生管理系统中用户的操作改写为常量的形式。
Project Structure–Modules–Import Module–包里的iml配置文件
代码:

import java.util.ArrayList;
import java.util.Scanner;

public class StudentSystem {
    private static final String ADD_STUDENT = "1";
    private static final String DELETE_STUDENT = "2";
    private static final String UPDATE_STUDENT = "3";
    private static final String QUERY_STUDENT = "4";
    private static final String EXIT = "5";

    public static void startStudentSystem() {
        ArrayList<Student> list = new ArrayList<>();
        loop:
        while (true) {
            System.out.println("------------欢迎来到学生管理系统-------------");
            System.out.println("1:添加学生");
            System.out.println("2:删除学生");
            System.out.println("3:修改学生");
            System.out.println("4:查询学生");
            System.out.println("5:退出");
            System.out.println("请输入您的选择:");
            Scanner sc = new Scanner(System.in);
            String choose = sc.next();
            switch (choose) {
                case ADD_STUDENT -> addStudent(list);
                case DELETE_STUDENT -> deleteStudent(list);
                case UPDATE_STUDENT -> updateStudent(list);
                case QUERY_STUDENT -> queryStudent(list);
                case EXIT -> {
                    System.out.println("退出");
                    System.exit(0);
                }
                default -> System.out.println("没有这个选项");
            }
        }
    }
}

四、权限修饰符

1.用来控制一个成员能够被访问的范围。
2.可以修饰成员变量,方法,构造方法,内部类。
3.有四种,作用范围由小到大(private < 空着不写(缺省/默认) < protected < public)
权限修饰符作用范围
权限修饰符

4.权限修饰符的使用规则:
1)实际开发中,一般只用private和public。
成员变量私有。方法公开。
2)特例:如果方法中的代码是抽取其他方法中的共性代码,这个方法一般也私有。

五、代码块

1.局部代码块(淘汰)
1)写在方法里的单独的大括号。节约内存。
2)提前结束变量的生命周期(已淘汰)。

public class Test {
    public static void main(String[] args) {
        //局部代码块(节约内存,淘汰)
        {
            int a = 10;
        }//当代码执行到这里时,变量a就从内存中消失了
        System.out.println(a);
    }
}

2.构造代码块(逐渐淘汰)
1)写在成员位置的代码块。
2)作用:可以把多个构造方法中重复的代码抽取出来(不够灵活)。
3)执行时机:我们在创建本类对象的时候会先执行构造代码块再执行构造方法。
3.静态代码块(掌握)
1)格式:static{}
2)特点:需要通过static关键字修饰,随着类的加载而加载,并且自动触发,只执行一次。
3)使用场景:在类加载的时候,做一些数据初始化的时候使用(重点)。
4.代码:

public class Student {
    private String name;
    private int age;

    //执行时机:
    //随着类的加载而加载的,并且只执行一次
    static {
        System.out.println("静态代码块执行了");
    }

/*    //构造代码块
    {
        System.out.println("开始创建对象了");
    }

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }*/

    //构造方法里有重复
/*    //第一种方法
    public Student() {
        //调用本类其他构造
        this(null,0);
    }

    public Student(String name, int age) {
        System.out.println("开始创建对象了");
        this.name = name;
        this.age = age;
    }*/

    //第二种方法
    public Student() {
        //调用方法
    }

    public Student(String name, int age) {
        //调用方法
        this.name = name;
        this.age = age;
    }

    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;
    }
}

import java.util.ArrayList;
import java.util.Scanner;

public class App {
    //静态代码块,初始化
    static ArrayList<User> list = new ArrayList<>();

    static {
        //添加一些用户信息
        list.add("川研", "123", "312123505009081234", "12345677890");
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("欢迎来到学生管理系统");
            System.out.println("请选择操作:1.登录 2.注册 3.忘记密码");
            String choose = sc.next();
            switch (choose) {
                case "1" -> login(list);
                case "2" -> register(list);
                case "3" -> forgetPassword(list);
                case "4" -> {
                    System.out.println("谢谢使用,再见");
                    System.exit(0);
                }//大括号不能省略
                default -> System.out.println("没有这个选项");
            }
        }
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值