day08笔记-多态-内部类+lambda等

回顾

接口

public interface 接口 extends 父接口1,父接口2 ... {
    
    
    public abstract 返回类型 方法名(参数); // 必须通过对象调用
    
    public static final 变量类型 变量名;
    
    // jdk8~jdk9
    public default 返回类型 方法名(参数) {
    
     // 必须通过对象调用
        // 方法实现
    }
    public static 返回类型 方法名(参数) {
    
     // 通过接口名调用
        // 方法实现
    }
}

实现

public classextends 父类1 implements 接口1, 接口2... {
    
    
    // 实现接口中的抽象方法
}

final

  • 类 - 类不能继承
  • 方法 - 方法不能重写
  • 变量 - 变量只能赋值一次,引用类型,引用地址不可改变了,引用对象内容 final 是不关心的

模板模式

把固定步骤放在父类的方法中,不固定步骤,在父类中表现为抽象方法,然后由子类实现

多态

  • 父子类关系(接口和实现类)
  • 方法发生重写
  • 父类变量 引用(指向)子类的对象

通用性

今日内容

耦合高的问题: 修改 dao 类,影响了 servcie 类,这种就称为耦合高

降低耦合目标就是:不管 dao 怎么该,service 的代码不受影响

做法

  1. 引入一个工厂类 (factory) 用来创建对象的类,我们这里用 工厂来生产 dao 对象,对于 service 只需要和 factory 打交道,至于 dao 的实际类型 service 并不关心
  2. 所有 dao 实现类需要一个共同的【接口】

1. 多态

定义、前提、好处

多态:一个父类(或接口)变量根据它所引用的对象的不同,而表现出不同的行为

前提:

  • 父子类关系(接口和实现类)
  • 方法发生重写
  • 父类变量 引用(指向)子类的对象

好处:

扩展性,通用性

只能通过父类来调用方法(只能看到父类中的方法)不能看到子类中特有方法,执行的是子类中重写后的方法

向上转型与向下转型

类图

Animal a = new Dog(); // 向上转型

Dog d = a; // 向下转型,编译出错

Dog d = (Dog) a; // 向下转型, 强制类型转换,就可以使用子类特有方法了

Animal b = new Cat();

Dog e = (Dog) b; // 不行, 必须有【是一个的关系】才能向下转换

instanceof       // instance 本意是实例,对象的意思  instanceof 就是判断该对象是否能转换为右侧的类型,它表达的是【是一个】的关系
    
对象 instanceof 类型  返回 true 表示左边对象可以被转换为右边类型, false 就表示不能转换
Animal +void eat Dog +void eat Cat +void eat Wolf +void eat Labrador Husky PersianCat Pet

练习

按上述类图,设计【一个】getAnimal 方法,接收动物名字,返回一种动物对象,例如参数为 “Dog” 返回 Dog 对象,参数为 “Hasky” 返回 Hasky 对象

提示:

  • 参数应该是 String 类型
  • 方法内可以用 switch 分支
  • 返回值类型是什么,自行思考?

接上题,判断根据上题返回的结果,再设计【一个】领养(adopt)方法

  • 只有 Pet 才能领养,返回该动物对象表示领养成功

  • 如果类型不是 Pet 返回 null 表示领养失败

提示:

  • 接收的参数为 Animal 类型
  • 返回值类型应该为 Pet 类型

参考解答

public class TestAnimal {
    
    

    public static void main(String[] args) {
    
    
        Animal a1 = getAnimal("Dog"); // 返回的实际对象是 Dog
        Animal a2 = getAnimal("Labrador"); // 返回的实际对象是 Labrador
        Animal a3 = getAnimal("Wolf"); // 返回的实际对象是 Wolf

        System.out.println(adopt(a1)); // 领养成功, 因为 Dog 是 Pet
        System.out.println(adopt(a2)); // 领养成功, 因为Labrador是 Pet(继承Dog间接地实现了Pet)
        System.out.println(adopt(a3)); // 领养失败,因为 Wolf 没有实现 Pet
    }
    public static Animal getAnimal(String name) {
    
    
        switch (name) {
    
    
            case "Dog":
                return new Dog();
            case "Cat":
                return new Cat();
            case "Wolf":
                return new Wolf();
            case "Labrador":
                return new Labrador();
            default:
                return null; // 没有该类型动物
        }
    }

    public static Pet adopt(Animal animal) {
    
    
        // 拉布拉多 是一个? 宠物
        if (animal instanceof Pet) {
    
    
            Pet pet = (Pet) animal;
            return pet;
        } else  {
    
    
            return null; // 领养失败
        }
    }

}
interface Pet{
    
    }
class Animal{
    
    }
class Dog extends Animal implements Pet{
    
    }
class Cat extends Animal implements Pet{
    
    }
class Wolf extends Animal{
    
    }
class Labrador extends Dog{
    
    }
class Husky extends Dog{
    
    }
class PersianCat extends Cat{
    
    }

练习2

public class Transport {
    
    
    static interface Vehicle {
    
    }
    static class Bus implements Vehicle {
    
    }
    public static void main(String[] args) {
    
    
        Bus bus = new Bus();
        boolean n = null instanceof Bus;
        boolean v = bus instanceof Vehicle;
        boolean b = bus instanceof Bus;
        System.out.println(n + " " + v + " " + b);
    }
}

A. true true true
B. false true true
C. false false false
D. None of the above

练习3

class Laptop extends Computer {
    
    
	String type = "laptop";
}
public class Computer {
    
    
    String type = "computer";
    public static void main(String[] args) {
    
    
        Computer computer = new Laptop();
        Laptop laptop = new Laptop();
        System.out.print(computer.type + "," + laptop.type);
    }
}

A. computer,laptop
B. laptop,computer
C. laptop,laptop
D. None of the above

2. 内部类(了解)

成员内部类

// 内部类作用
// 1. 更精确的表达抽象时的嵌套关系
// 2. 内部类可以访问外部类的私有成员, 如果是平级关系的类则无法做到
// 3. 一般会在 Person 类内来创建并使用 Head 和 Body 这样的内部类
public class Person {
    
    
    private String name;
    private int age;
    private static int x;

    private Head head = new Head(); // 头部
    private Body body = new Body(); // 身体

    class Head {
    
    
        private String mouth;
        private String eyes;
        private String nose;
        private String ears;
        public void print() {
    
    
            System.out.println(name + "的相貌是:" + mouth);
        }
    }

    private class Body {
    
    
    }

}

静态内部类

应用:防止平时做练习时的类名冲突,例如下面

public class TestStudent1 {
    
    
    // 此 Student 有 id, name 属性
    static class Student{
    
    
        int id;
        String name;
    }
    public static void main(String[] args) {
    
    
        Student s = new Student();
        s.id = 1;
        s.name = "张三";
    }
}

public class TestStudent2 {
    
    
    // 此 Student 只有 name 属性
    static class Student{
    
    
        String name;
    }
    public static void main(String[] args) {
    
    
        Student s = new Student();
        s.name = "李四";
    }
}

中的 Student 类是可以独立测试使用,互不干扰

成员内部类与静态内部类的区别

public class TestOuter {
    
    
    public static void main(String[] args) {
    
    
        Outer1.Inner1 inner1 = new Outer1.Inner1();   // 静态内部类创建
        Outer1.Inner2 inner2 = new Outer1().new Inner2(); // 成员内部类创建
    }
}

class Outer1 {
    
    
    private int x;
    private static int y;
    static class Inner1 {
    
    
        public void test() {
    
    
            System.out.println(x); // 编译出错,静态内部类不能访问外部类的成员变量
            System.out.println(y); // 可以访问外部类的静态成员变量
        }
    }
    class Inner2 {
    
    
        public void test() {
    
    
            System.out.println(x); // 静态内部类可以访问外部类的成员变量
            System.out.println(y); // 可以访问外部类的静态成员变量
        }
    }
}

局部内部类

public void test(){
    
    
    // 局部内部类中如果访问【外层方法的局部变量】,此局部变量相当于是 final,只能读,不能改
    // 同样适用于 匿名内部类
    final int t = 10;

    class Inner3 {
    
    
        public void x() {
    
    
            System.out.println(t);
            t = 20; // 编译出错
        }
    }
}

匿名内部类

配合抽象类和接口使用

接口 变量名 = new 接口() {
    
    
    实现抽象方法
}
变量名.抽象方法()

3. lambda(了解)

在某些场景下对匿名内部类做简化

函数,(对应着java中的方法),只关心输入和输出,不关系方法名,方法属于哪个类

  • 行为的参数化
@FunctionalInterface // 检查此接口是否是函数式接口(是否只有一个抽象方法)
interface Comparator {
    
    
    // 抽象方法只有一个
    int compare(String o1, String o2);
    
    // 默认方法随意
    default int aaa(){
    
    
        return 1;
    }
}

// 对应的 lambda 
(o1, o2) -> {
    
    
    return 正数或负数或零
}

函数式接口 - 只有一个抽象方法的接口

  • Comparator

  • Consumer

  • Function

  • Predicate

  • Supplier

猜你喜欢

转载自blog.csdn.net/weixin_46661406/article/details/107033019
今日推荐