# 泛型

## 函数中， 参数使用泛型

考虑这样一个场景： 我们要给 NumGeneric 对象 中一个成员变量num赋值, 但是num的数据类型我们还不确定。它可能是int ,也可能是 float, 还可能是别的类型。此时我们对于这种不确定的数据类型, 可以用泛型代替。泛型的使用，需要在 类名 后加入 < > 体现出来。如下面的public class NumGeneric\<E>。

```java
public class NumGeneric<E> {

    private E num;

    public NumGeneric(E num) {
        this.num = num;
    }

    public E getNum() {
        return num;
    }

    public static void main(String[] args) {

        NumGeneric<Double> numObj= new NumGeneric<>(25.0);

        System.out.println("Num : "+ numObj.getNum());

    }
}
```

## 自定义泛型

有时候, 基础的数据类型很难满足我们的实际需求。我们需要构建自己的泛型。

考虑以下的场景: 有一个 抽象类 Goods, 还有一个 Book 类继承 Goods 类, 还有一个 Shoes 类也继承 Goods 类。有一个 GoodsSellor 类 用于销售多件商品,  但是具体销售什么商品不确定，有可能销售 Book 对象, 也有可能销售 Shoes 对象，也有可能两种商品都有。这时我们在 GoodsSellor 传入参数是,  可以用泛型 \<? extends Goods> 代替 具体的 商品类型。\<? extends Goods> 表示任何一种继承 Goods 的类型。

编写Goods 类, 设置成是抽象类, 不能被实例化, 专门用来给子类继承

```java
public abstract class Goods {
    public abstract void sell();
}
```

编写 Book 类, 继承 Goods 类

```java
public class Book extends Goods {

    @Override
    public void sell() {
        System.out.println("sell books");
    }
    
}
```

编写 Shoes 类，继承 Goods 类

```java
public class Shoes extends Goods {
    @Override
    public void sell() {
        System.out.println("sell shoes");
    }
}
```

编写 GoodsSeller 类, 用来销售 Goods 的子类

**我们使用了 \<? extends Goods> 来代替 Goods 的所有子类**

```java
public class GoodsSeller  {

    public GoodsSeller() {
    }

    public void sellGoods(List<? extends Goods> goods) {

        for(Goods g:goods) {
            g.sell();
        }

    }

    public static void main(String[] args) {
        GoodsSeller gs=new GoodsSeller();

        List<Goods> goods=new ArrayList<>();
        goods.add(new Shoes());
        goods.add(new Book());

        gs.sellGoods(goods);
        //输出 :
        //sell shoes
        //sell books
    }


}
```
