javaSE&多态

简介: javaSE&多态

斜体样式1.1 面向对象三大特征 ?

  • 封装 , 继承 , 多态


1.2 什么是多态 ?斜体样式


  • 一个对象在不同时刻体现出来的不同形态


  • 举例 : 一只猫对象

  我们可以说猫就是猫 : Cat cat = new Cat();

  我们也可以说猫是动物 : Animal cat = new Cat();

  这里对象在不同时刻,体现出来的不同形态 , 我们就可以理解为多态


1.3 多态的前提


  • 有继承/实现关系
  • 有方法重写
  • 父类的引用指向子类的对象
/*
    多态的三个前提条件
        1 需要有继承/实现关系
        2 需要有方法重写
        3 父类的引用指向子类的对象
 */
public class AnimalTest {
    public static void main(String[] args) {
        // 3 父类的引用指向子类的对象
        // 多态形式对象
        Animal a = new Cat();
    }
}

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

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

1.4 多态的成员访问特点


  • 构造方法 : 和继承一样 , 子类通过super()访问父类的构造方法
  • 成员变量 : 编译看左边(父类) , 执行看左边(父类)
  • 成员方法 : 编译看左边(父类) , 执行看右边(子类)
/*
    多态的成员访问特点 :
        1 构造方法 : 和继承一样 , 都是通过super()访问父类的构造方法
        2 成员变量 : 编译看左边(父类) , 执行看左边(父类)
        3 成员方法 : 编译看左边(父类) , 执行看右边(子类) , 注意 , 如果执行时
            1) 子类没有回动态去找父类中的方法
            2) 子类的特有方法无法进行调用(多态的缺点)
 */
public class MemberTest {
    public static void main(String[] args) {
        // 父类的引用指向子类的对象
        Fu f = new Zi();

        // 多态对象调用成员变量
        System.out.println(f.num);

        // 多态对新乡调用调用成员方法
        f.show();

        // 多态对象不能调用子类特有的方法
        // f.show2();
    }
}

class Fu {
    int num = 100;

    public void show() {
        System.out.println("父类的show方法");
    }
}

class Zi extends Fu {
    int num = 10;

    public void show() {
        System.out.println("子类的show方法");
    }

    public void show2(){
        System.out.println("子类特有的方法");
    }
}

1.5 多态的优缺点


  • 优点 : 提高代码的扩展性
  • 缺点 : 不能调用子类特有的功能
public abstract class Animal {
    private String breed;
    private String color;

    public Animal() {
    }

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

    public String getBreed() {
        return breed;
    }

    public void setBreed(String breed) {
        this.breed = breed;
    }

    public String getColor() {
        return color;
    }

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

    public abstract void eat();
}

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

    public Cat(String breed, String color) {
        super(breed, color);
    }

    @Override
    public void eat() {
        System.out.println("猫吃鱼...");
    }

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

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

    public Dog(String breed, String color) {
        super(breed, color);
    }

    @Override
    public void eat() {
        System.out.println("狗吃骨头!");
    }

    public void lookDoor(){
        System.out.println("狗看门...");
    }
}


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

    public Pig(String breed, String color) {
        super(breed, color);
    }

    @Override
    public void eat() {
        System.out.println("猪拱白菜...");
    }

    public void sleep() {
        System.out.println("一直再睡...");
    }
}

/*
    如果方法的参数是一个类的话 , 那么调用此方法需要传入此类的对象 , 或者子类对象

    多态的好处 :
        提高代码的扩展性 , 灵活性
    多态的缺点:
        不能调用子类的特有功能
 */
public class AnimalTest {
    public static void main(String[] args) {
        useAnimal(new Cat());

        System.out.println("---------");

        useAnimal(new Dog());

        System.out.println("---------");

        useAnimal(new Pig());
    }

    public static void useAnimal(Animal a){// Animal a = new Dog()
        a.eat();
        // 多态不能访问子类特有的功能
        // 如果解决 ?

        // 向下转型
        if(a instanceof Cat) {
            Cat cat = (Cat) a;
            cat.catchMouse();
        }
        if(a instanceof Dog) {
            Dog dog = (Dog) a;
            dog.lookDoor();
        }

        if(a instanceof Pig) {
            ((Pig) a).sleep();
        }
    }

//    // 定义一个使用猫类的方法
//    public static void useAnimal(Cat c) {// Cat c = new Cat();
//        c.eat();
//        c.catchMouse();
//    }
//
//    // 定义一个使用狗类的方法
//    public static void useAnimal(Dog d) {// Dog d = new Dog();
//        d.eat();
//        d.lookDoor();
//    }
//
//    // 定义一个使用猪类的方法
//    public static void useAnimal(Pig pig) {
//        pig.eat();
//        pig.sleep();
//    }
}


1.6 多态的转型


  • 向上转型 : 把子类类型数据转成父类类型数据 Animal a = new Cat();
  • 向下转型 : 把父类类型数据转成子类类型数据 Cat cat = (Cat)a;


1.7 多态的转型注意


  • 如果被转的对象 , 对应的实际类型和目标类型不是同一种数据类型 , 那么转换时会出现ClassCastException异常
异常代码如下
public static void main(String[] args) {
    Animal a = new Cat();
    useAnimal(a);
}
public static void useAnimal(Animal a) {
    Dog d = (Dog) a;
    d.eat();
}

1.8 解决转型安全隐患


使用关键字 instanceof

作用 : 判断一个对象是否属于一种引用数据类型

格式 : 对象名 instanceof 引用数据类型

通俗的理解:判断关键字左边的变量,是否是右边的类型,返回boolean类型结果


2 内部类


2.1 内部类的分类


什么是内部类 ?

  • 一个A类 中 定义一个B类 , 那么B类就属于A类的内部类 , A类就属于B类的外部类


什么时候使用内部类 ?

  • 多个事物之间有包含关系, 可以使用内部类


内部类分类 ?

  • 成员内部类
  • 局部内部类
  • 匿名内部类


2.2 成员内部类


  • 定义的位置 : 类中方法外


  • 创建成员内部类对象格式 : 外部类名.内部类名 对象名 = new 外部类名().new 内部类名(参数);


// 外部类
public class Person {
    // 成员内部类
    public class Heart {
        // 频率变量
        private int rate;
        // 跳动方法
        public void beats() {
            System.out.println("咚咚咚!");
        }
    }
}

class Test {
    public static void main(String[] args) {
        // 创建内部类对象
        Person.Heart heart = new Person().new Heart();
        // 调用内部类中的方法
        heart.beats();
    }
}

成员内部类访问外部类的成员

  • 在内部类中有代表外部类对象的格式 : 外部类名的.this , 私有的也可以访问
  • 外部类要想访问内部类成员 , 需要创建内部类对象
public class Person {
    private String name = "张三";
    private int num = 10;
    
    // 成员内部类
    public class Heart {
        int num = 100;
        // 频率
        private int rate;
        // 跳动
        public void beats() {
            System.out.println("咚咚咚!");
        }
        // 调用外部类的成员
        public void show(){
            int num = 1000;
            System.out.println(Person.this.name);
            System.out.println(num);// 1000 就近原则
            System.out.println(this.num);// 100
            System.out.println(Person.this.num);// 10

        }
    }
}

class Test {
    public static void main(String[] args) {
        Person.Heart heart = new Person().new Heart();
        heart.beats();
        heart.show();
    }
}

2.3 匿名内部类


  • 匿名内部类 : 没有名字的类 , 一次性产品
  • 使用场景 : 直接调用方法 , 作为方法的传参 , 返回值类型
  • 好处 : 简化代码 , 快速实现接口或者抽象的抽象方法
  • 格式 :

   new 类名/接口名(){ 重写抽象方法 } 注意 : 此处创建的是子类对象!!!

  • 使用方式 :

   直接调用方法

   作为方法的参数传递

   作为方法的返回值类型

//接口
interface Flyable {
    void fly();
}
// 直接调用方法
Flyable f1 = new Flyable() {
    @Override
    public void fly() {
        System.out.println("不知道什么在飞.....");
    }
};
f1.fly();
// 作为方法的参数传递
showFlyable(
    new Flyable() {
        @Override
        public void fly() {
            System.out.println("不知道什么在飞3333");
        }
    }
);

public static void showFlyable(Flyable flyable) {
  flyable.fly();
}
// 作为方法的返回值类型
public static Flyable getFlyable() {
  return new Flyable() {
        @Override
        public void fly() {
            System.out.println("3333333333333");
        }
    };
}
/*
    1 如果方法的参数是一个类的话 , 调用此方法需要传入此类的对象或者此类的子类对象
    2 如果方法的返回值类型是一个类的话 , 需要返回此类的对象 , 或者此类的子类对象

     3 如果方法的参数是一个接口的话 , 调用此方法需要传入此接口的实现类对象
     4 如果方法的返回值类型是一个接口的话 , 需要返回此接口的实现类对象


     匿名内部类 : 代表的就是子类对象!!!
        new 类名/接口名(){
            重写抽象类或者接口中的抽象方法
        };

     使用方向 :
        1 调用方法
        2 作为方法参数传递
        3 作为方法的返回值
 */
public interface Swim {
    public abstract void swimming();
}

class Test {
    public static void main(String[] args) {
//        // 子类对象!!!
        //  1 调用方法
//       new Swim() {
//            @Override
//            public void swimming() {
//                System.out.println("匿名内部类 , 重写了接口中的抽象方法...");
//            }
//        }.swimming();


//        //   2 作为方法参数传递
//        useSwim(new Swim() {
//            @Override
//            public void swimming() {
//                System.out.println("匿名内部类 , 重写了接口中的抽象方法...");
//            }
//        });

//        // 3 作为方法的返回值
//        Swim s = getSwim();
//        s.swimming();
    }


    public static Swim getSwim() {
        return new Swim() {
            @Override
            public void swimming() {
                System.out.println("匿名内部类 , 重写了接口中的抽象方法...");
            }
        };
    }


    /*
        Swim swim = new Swim() {
            @Override
            public void swimming() {
                System.out.println("匿名内部类 , 重写了接口中的抽象方法...");
            }
        };
     */
    public static void useSwim(Swim swim) {
        swim.swimming();
    }
}
相关文章
|
6月前
|
Java 编译器
【JavaSE】面向对象之多态
【JavaSE】面向对象之多态
|
9月前
|
Java 编译器
【JAVASE】类与对象 中
【JAVASE】类与对象
|
9月前
|
Java 编译器
【JAVASE】类与对象 下
【JAVASE】类与对象
|
9月前
|
存储 Java 编译器
【javaSE】 类和对象详解(下)
【javaSE】 类和对象详解(下)
|
9月前
|
安全 Java
【JAVASE】多态 下
【JAVASE】多态
|
6月前
|
安全 Java 程序员
JavaSE继承和多态
JavaSE继承和多态
|
6月前
|
Java 程序员 编译器
【JavaSE】面向对象之继承
【JavaSE】面向对象之继承
|
8月前
|
存储 安全 Java
类和对象【JavaSE】
类和对象【JavaSE】
64 0
|
9月前
|
Java 编译器
【JAVASE】多态 上
【JAVASE】多态
|
9月前
|
Java Android开发
【javaSE】 类和对象详解(上)
【javaSE】 类和对象详解(上)

热门文章

最新文章