Java学习(多态,包和final,权限修饰符和代码块)

多态 

多态顾名思义多种形态 

Java学习(多态,包和final,权限修饰符和代码块)_第1张图片

那么多态有什么用呢?

来看看下面这个例子:

如果有三个人:老师  学生  管理员它他们分别要要在学生管理系统上注册,调用三个函数的话也可以  以

public void register(Student s){
        s.show();
    }

但是如果人数很多呢?还一个一个这样创建吗?显然不合适.这就可以运用到多态的知识,还是以上面的三个人为例,他们都有共性都是人那么就可以运用继承里的知识点创建一个父类Person 

Java学习(多态,包和final,权限修饰符和代码块)_第2张图片这样就可以只创建一个方法,多个对象都可以进行调用了. 

Java学习(多态,包和final,权限修饰符和代码块)_第3张图片

 多态的好处?

使用父类型作为参数,可以接收所有子类对象,体现多态的扩展性和便利.

下面是代码验证上面所说的知识:

Person类:

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

Test类:

public class Test {
    public static void main(String[] args) {
        //这个方法既能接受老师,又能接受学生把参数学成这个三个类型的父类
        Student s =new Student();
        s.setName("yjy");
        s.setAge(18);

        Teacher t = new Teacher();
        t.setName("Mrs.white");
        t.setAge(25);

        Administrator admin = new Administrator();
        admin.setAge(30);
        admin.setName("joy");

        //创建完三个对象,并且调用register方法
        register(s);
        register(t);
        register(admin);

    }
    public static void register (Person p){
        p.show();
    }
}

运行结果:

 
  

多态调用成员的特点

变量调用:编译看左边,运行也看左边.

方法调用:编译看左边,运行看右边.

package a02polymorphismdemo2;

public class Test {
    public static void main(String[] args) {
        //创建方式(多态方式)
        //Fu f =new Zi();
        Animal a =new Dog();
        //用多态方式调用成员变量:编译看左边,运行也看左边
        //编译看左边:Java编译代码的时候,会看左边的父类中有没有这个变量,如果有则编译成功,如果没有则编译失败
        //如果把父类中 String name="动物";删除的话 就编译失败 程序根本无法运行
        //运行也看左边:java运行代码的时候,实际获取的就是左边父类成员变量的值
        System.out.println(a.name);//动物
        //调用成员方法:编译看左边,运行看右边
        //编译看左边:Java编译代码的时候,会看左边的父类中有没有这个变量,如果有则编译成功,如果没有则编译失败
        //如果把父类中public void show()注释掉 那么将编译失败 程序无法运行
        //运行看右边:java运行代码的时候,实际运行的是子类中的方法
        a.show();//Dog ---show方法

        //理解:
        //Animal a =new Dog();
        //现在用a去调用变量和方法
        //而a是Animal类型的,所以默认都会是Animal这个类中找

        //成员变量:在子类对象中,会把父类中的成员变量也继承下来的.父:name 子:name
        //以前我们是这样调用的:Dog d =new Dog();也就是用d去调用成员变量 然后他的类型是
        //Dog因此的到的也就是Dog的成员变量
        //现在是Animal类型 因此得到的也就是Animal类型的成员变量

        //成员方法:如果子类对方法进行了重写,那么在虚方法表中是会把父类的方法进行覆盖的.
        //什么是虚方法表?继承那篇文章有说明,也就是非static 非final 非private
        
    }
}
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方法");
    }
}

Java学习(多态,包和final,权限修饰符和代码块)_第4张图片

多态的优势和弊端 

在多态形势下:右边对象可以实现解耦合,便于扩展和维护.

Person p = new Student();

p.work();//业务逻辑发生改变时,后续代码无需修改

定义方法的时候,使用父类型作为参数,可以接收所有子类对象,体系多态的扩展性和便利.

Java学习(多态,包和final,权限修饰符和代码块)_第5张图片

可以把任意的对象都往里面放 这也是多态的一个优势 

public class Test {
    public static void main(String[] args) {
        //ArrayList list =new ArrayList<>();
        //这里表示只能把字符串往里面添加不能添加其他的
        //如果不写泛型 也就是下面这样
        ArrayList list =new ArrayList();
        //这就表示所有的类型都可以往里面添加
        
    }
}
 
  

弊端:(代码形式分析)

package a02polymorphismdemo2;

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

        //多态的弊端:
        //不能调用子类的特有功能
        //a.lookHome();
        //报错的原因?
        //当调用成员方法的时候,编译看左边,运行看右边
        //那么在编译的时候先检查左边父类中有没有这个方法,如果没有直接报错

        //解决方案:
        //变回子类类型就可以了
//        int b=10;
//        byte c =(byte)b;
        Dog d = (Dog) a;//大变小alt +回车
        d.lookHome();
        //细节:转换的时候不能瞎转,如果转成其他类的类型就会报错
//        Cat c =(Cat) a;//狗不能转成猫
//        c.catchMouse();
//        if(a instanceof Dog){
//            Dog c =(Dog)a;
//            //a是不是狗
//        }else if(a instanceof Cat){
//            Cat c =(Cat)a;
//        }else{
//            System.out.println("没有这个类型,无法转换");
//        }
        //新特性:
        //先判断a是否为Dog类型 如果是 则强转成Dog类型 转换之后变量名为a
        if(a instanceof Dog d){
            d.lookHome();
        }else if(a instanceof Cat c){
            c.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 lookHome(){
        System.out.println("狗看家");
    }
}
class Cat extends Animal{
    @Override
    public void eat(){
        System.out.println("猫吃小鱼干");
    }
    public void catchMouse(){
        System.out.println("猫抓老鼠");
    }
}

多态的综合练习

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

    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 somethind)方法打印内容如下:
            年龄为30岁的老王养了一只黑颜色的2岁的狗
            2岁的黑颜色的狗两只前腿死死的抱住骨头猛吃
        keepPet(Cat cat,String somethind)方法打印内容如下:
            年龄为25岁的老李养了一只灰颜色的3岁的猫
            3岁的灰颜色的猫眯着眼睛侧着头吃鱼
    5.思考:        
        1.Dog和Cat都是Animal的子类,以上案例中针对不同的动物,定义了不同的keepPet方法,过于繁琐,能否简化,并体会简化后的好处?
        2.Dog和Cat虽然都是Animal的子类,但是都有其特有方法,能否想办法在keepPet中调用特有方法?

Animal类:

public class Animal {
    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);
    }
}

在Java继承中我们说过:

Java学习(多态,包和final,权限修饰符和代码块)_第6张图片

 cat类:

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

    public Cat(int age, String color) {
        super(age, color);
    }

    @Override
    public void eat(String something) {
        System.out.println(getAge()+"岁的"+getColor()+"颜色的猫眯着眼睛侧着头吃"+something);

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

Dog类:

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

    public Dog(int age, String color) {
        super(age, color);
    }

    @Override
    public void eat(String something) {
        System.out.println(getAge()+"岁的"+getColor()+"颜色的狗两只前腿死死的抱住"+something+"猛吃");
    }
    public void lookHome(){
        System.out.println("狗在看家");
    }
}

Person类:

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 keepPet(Dog dog,String something){
//        System.out.println("年龄为"+age+"岁的"+name+"养了一只"+dog.getColor()+"颜色的"+dog.getAge()+"岁的狗");
//        dog.eat(something);
//    }
//    public void keepPet(Cat cat,String something){
//        System.out.println("年龄为"+age+"岁的"+name+"养了一只"+cat.getColor()+"颜色的"+cat.getAge()+"岁的猫");
//        cat.eat(something);
    //想要一个方法,能够接收所有的动物,包括猫,包括狗
    //方法的形参,可以写这些类,Animal
    public void keePet(Animal a,String something){
        if(a instanceof Dog d){
            System.out.println("年龄为"+age+"岁的"+name+"养了一只"+d.getColor()+"颜色的"+d.getAge()+"岁的狗");
            d.eat(something);
        }
        else if(a instanceof Cat c){
            System.out.println("年龄为"+age+"岁的"+name+"养了一只"
                    +c.getColor()+"颜色的"+c.getAge()+"岁的动物");
            c.eat(something);
        }else{
            System.out.println("没有这种动物");
        }
    }
}

Test:

public class Test {
    public static void main(String[] args) {
        //创建对象并调用方法
//        Person p1 =new Person("老王",30);
//        Dog d =new Dog(2,"黑");
//        p1.keepPet(d,"骨头");
//
//        Person p2=new Person("老李",25);
//        Cat c =new Cat(3,"灰");
//        p2.keepPet(c,"鱼");
        //创建饲养员对象
        Person p1 =new Person("老王",30);
        Dog d =new Dog(2,"黑");
        Cat c =new Cat(3,"灰");
        p1.keePet(d,"骨头");
        p1.keePet(c,"鱼");

    }
}

什么是包?

包就是文件夹.用来管理不同功能的Java类,方便后期代码维护

包名的规则:公司域名反写+包的作用,需要全部英文小写,见名知意.com.yjy.domain

pack com.yjy.domain

public class Student{

        私有化成员变量

        构造方法                -------------------------> com.yjy.domain.Student(全类名,全限定名)

        成员方法

}

使用其他类的规则

使用其他类时,需要使用全类名.

public class Test {
    public static void main(String[] args) {
        com.yjy.donmain.Student s =new com.yjy.donmain.Student();
    }
}
import com.yjy.donmain.Student;
public class Test {
    public static void main(String[] args) {
        Student s =new Student();
    }
}

使用同一个包的类时,不需要导包

使用java.lang包中的类时,不需要导包

其他情况都需要导包

如果同时使用两个包中的同名类,需要用全类名

final

最终的----------->不可改变的

方法:表明该方法是最终方法,不能重写

类:表明这个类是最终类,不能被继承

变量:叫做常量,只能被赋值一次

常量

实际开发中,常量一般作为系统的配置信息,方便维护,提高可读性.

常量的命名规范:

单个单词:全部大写

多个单词:全部大写,单词之间用下划线隔开

细节:

final修饰的变量是基本类型,那么变量存储的数据值不能发生改变

final修饰的变量是引用类型,那么变量存储的地址值不能发生改变,对象内部的可以改变

权限修饰符

权限修饰符:是用来控制一个成员能够被访问的范围的.

可以修饰成员变量,方法,构造方法,内部类

Java学习(多态,包和final,权限修饰符和代码块)_第7张图片

 private:只能自己用

默认/缺省:只能在本包用

protected:受保护的

public:公共的

代码块

局部代码块

{}:提前结束变量的生命周期.这个技术现在已经用不到了,因为现在计算机的硬件很强大 内存很大

Java学习(多态,包和final,权限修饰符和代码块)_第8张图片

构造代码块

作用:把重复代码放到构造代码块中,写在成员位置的代码块 执行时机:优先于构造方法执行

这个技术也渐渐淘汰了 这种写法不够灵活 因为只要卸载构造代码块中就一定会执行 太死板

Java学习(多态,包和final,权限修饰符和代码块)_第9张图片

Java学习(多态,包和final,权限修饰符和代码块)_第10张图片

可以这么写:

Java学习(多态,包和final,权限修饰符和代码块)_第11张图片

Java学习(多态,包和final,权限修饰符和代码块)_第12张图片

静态代码块

格式:static{}

特点:需要通过static关键字修饰,随着类的加载而加载,并且自动触发,只执行一次

使用场景:在类加载的时候,做一些数据初始化的时候使用

数据初始化:在学生管理系统中

Java学习(多态,包和final,权限修饰符和代码块)_第13张图片

Java学习(多态,包和final,权限修饰符和代码块)_第14张图片

你可能感兴趣的:(Java,java,开发语言)