java 泛型

背景

 JAVA推出泛型以前,程序员可以构建一个元素类型为Object的集合,该集合能够存储任意的数据类型对象,而在使用该集合的过程中,需要程序员明确知道存储每个元素的数据类型,否则很容易引发ClassCastException异常。

什么是泛型

泛型的本质就是参数化类型,也就是所操作的数据类型被指定为一个参数。

泛型类的定义语法

   /**
     * class类名称<泛型标识,泛型标识, … > {
     * 	private 泛型标识变量名;
     * 	.....
     * }
     */
  public class ProductGetter<T> {
    private T product;
    ArrayList<T> list = new ArrayList<>();
    public void addProduct(T t){
        list.add(t);
    }
    public T getProduct(){
        return list.get(new Random().nextInt(list.size()));
    }
  }
使用语法
  • 常用的泛型标识:T、E、K、V
  • 类名<具体的数据类型>对象名= new类名<具体的数据类型>();
  • Java1.7以后,后面的<>中的具体的数据类型可以省略不写类名<具体的数据类型>对象名= new类名<>();
  • 引用数据类型。因为基本类型没有继承object 基本数据类型是在栈中创建的,存储的是值本身。引用数据类型本体在堆中,栈中存的是堆中的指针
  • 同一泛型类型,根据不同的数据类型创建的对象,本质上是同一类型
泛型类注意事项
  • 泛型类,如果没有指定具体的数据类型,此时,操作类型是0bject
  • 泛型的类型参数只能是类类型,不能是基本数据类型
  • 泛型类型在逻辑上可以看成是多个不同的类型,但实际上都是相同类型
  • 子类也是泛型类,子类和父类的泛型类型要一致class ChildGeneric<T> extends Generic<T>
  • 子类不是泛型类,父类要明确泛型的数据类型class ChildGeneric extends Generic<String>
  • 泛型类派生子类,子类也是泛型类,那么子类的泛型标识要和父类一致。
泛型接口的定义语法
interface 接口名称〈泛型标识,泛型标识,…> {泛型标识方法名();
.....
}
泛型接口的使用
  • 实现类不是泛型类,接口要明确数据类型 实现类也是泛型类,
  • 实现类和接口的泛型类型要一致
  • 实现泛型接口的类,不是泛型类,需要明确实现泛型接口的数据类型。
泛型方法
修饰符<T,E,...> 返回值类型 方法名(形参列表){方法体}
  • public 与返回值中间的<T>非常重要,可以理解为声明此方法为泛型方法只有声明了<T>的方法才是泛型方法,
  • 泛型类中使用了泛型成员的方法并不是泛型方法<T>表示该方法将使用泛型类型T,此时才可以在方法中试用贴泛型类型T
  • 与泛型类的定义一样,此处的T可以为任意标识,常见的T、E、K、V等形式参数都常用于表示泛型
//定义泛型方法
//list 参数
//<E> 泛型标识,具体类型,由调用方法的时候来指定
public <E> E getProduct(ArrayList<E> list){
  return list.get(random.nextInt(list.size()))
}
//泛型 方法的使用
public class Test{
  public static void main(String[] args){
    ProductGetter<Integer> productGetter = new ProductGetter<>();
    ArrayList<String> strList = new ArrayList<>();
    strList.add("笔记本电脑");
    strList.add("苹果手机");
    strList.add("扫地机器人");
    //泛型方法的调用,类型是通过调用方法的时候指定的;这里定义的泛型方法的类型是独立与类类型存在的,如果是成员方法则和泛型类的类型一致
    System.out.println(productGetter.getProduct(strList)); 
   ArrayList<Integer> intList = new ArrayList<>();
   inList.add(1000);
   inList.add(5000);
   inList.add(3000);
   Integer product2 = productGetter.getProduct(intList);
   System.out.println(product2+"\t"+product2.getClass().getSimpleName)
  }
}
//定义多个泛型的方法
public static <T,E,K> void printType(T t,E e ,K k){
  System.out.println(t + "\t" + t.getClass().getSimpleName());
  System.out.println(t + "\e" + e.getClass().getSimpleName());
  System.out.println(t + "\k" + k.getClass().getSimpleName());
}
//调用多个泛型类型的静态方法
ProductGetter.prinType(100, "java", true)
泛型方法与可变参数

//泛型0可变参数的定义
public <E> void print(E... e){
  for(E el : e){
    System.out.println(e);
  }
}
//可变参数泛型方法的调用
ProductGetter.print(1, 2, 3, 4, 5);
泛型方法的总结
  • 泛型方法能使方法独立于类而产生变化
  • 如果static方法要使用泛型能力,就必使其成为泛型方法
public static void main(String[] args){
  Box<Number> box1 = new Box<>();
  box1.setFirst(100)showBox(box1)Box<Integer> box2 = new Box<>();
  box2.setFiorst(200);
  showBox(box2);
}
public static void showBox(Box<? extends NUmber> box){
     Number first = box.getFirst();
     System.out.println(first);
}
类型通配符的上限
/接口<? extends 实参类型>
  • 要求该泛型的类型名,只能事实参类型,或实参类型的子类型
  • 类型通配符的下限
  • 类/接口<? super 实参类型>
  • 要求该泛型的类型名,只能事实参类型,或实参类型的父类型
//上下限演示代码
/**
 * @author : zpb
 * @date : 2022/7/3016:24
 * @description : some description
 */
@Slf4j
@SpringBootTest
public class AnimalTest {
    @Test
    public void Main(){
        ArrayList<Animal> animals = new ArrayList<>();
        ArrayList<Cat> cats = new ArrayList<>();
        ArrayList<MiniCat> miniCats = new ArrayList<>();
//        showAnimal(animals);
        showAnimal(cats);
        showAnimal(miniCats);
        
        showAnimals(animals);
        showAnimals(cats);
//        showAnimals(miniCats);
        TreeSet<Cat> animals1 = new TreeSet<>(new Comparator1());
        animals1.add(new Cat("jerry", 20));
        animals1.add(new Cat("amy", 25));
        animals1.add(new Cat("frank", 35));
        animals1.add(new Cat("jim", 15));
        for (Cat cat:
                animals1) {
            System.out.println(cat);
        }
    }
    /**
     * 泛型上限通配符,传递的集合类型,只能是Car或Car子类类型
     * @param list
     */
    public static void showAnimal(ArrayList<? extends Cat> list){
        //不允许在这里对list进行追加,因为list类型无法确定
        for (Cat c:
                list) {
            System.out.println(c);
        }
    }
    /**
     * 类型通配符下限,要求集合只能是Cat或Cat的父类类型
     */
    public static void showAnimals(List<? super Cat> list){
        //这里允许对list进行追加,但不能保证对元素的约束要求
        for (Object c:
                list) {
            System.out.println(c);
        }
    }
}
class Comparator1 implements Comparator<Animal> {
    @Override
    public int compare(Animal o1, Animal o2) {
        return o1.getName().compareTo(o2.getName());
    }
}
class Comparator2 implements Comparator<Cat> {
    @Override
    public int compare(Cat o1, Cat o2) {
        return o1.getAge()-o2.getAge();
    }
}
class Comparator3 implements Comparator<MiniCat> {
    @Override
    public int compare(MiniCat o1, MiniCat o2) {
        return o1.getLevel()-o2.getLevel();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值