泛型详解及使用及通配符(一)

目录

参考资料

一、泛型类

二、泛型接口

1.基本语法

三、泛型方法

1.概述

 2.难点及易混点解答​​​​​​​


参考资料


一、泛型类​​​​​​​

  • 首先泛型类的基本语法
public class 类名称 <泛型标识,泛型标识,...>{

    private 泛型标识 变量名;

    public 泛型标识 testMethod(泛型标识 a,泛型标识 b){}

    ...
}

常用的泛型标识: T ,E ,K ,V
  • 泛型的使用方式 
类名<具体的数据类型> 对象名 = new 类名<>();
  •  例如:
public class Demo01<T,E,K,V> {

    private T attribute1;

    private E attribute2;

    private K attribute3;

    private V attribute4;

    private String attribute5;

    public T test_01(String str,E e,K k,V v){
        return null;
    }
    
}

Demo01<String, Integer, Boolean, Double> Demo01 = new Demo01<>();

  •  下面是具体使用
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Pair<T> {

    private String orderName;
    private int orderId;
    private T first;
    private T last;

}

    @Test
    public void test_1(){
        //泛型类在创建对象的时候,来指定操作的具体数据类型。
        //泛型类在创建对象的时候,没有指定类型,将按照Object类型来操作。
        //泛型类,不支持基本数据类型。
        Pair<String> pair1 = new Pair<>("default",0,"firstStr","secondStr");
        Pair<Integer> pair2 = new Pair<>("default",0,1,2);
        //Pair<int> pair3 = new Pair<>("default",0,1,2);
        Pair pair4 = new Pair<>("default",0,1,"string");

        //同一泛型类,根据不同的数据类型创建的对象,本质上是同一类型。
        System.out.println(pair1.getClass());
        System.out.println(pair2.getClass());
        System.out.println(pair4.getClass());
        System.out.println(pair1.getClass() == pair2.getClass());
        System.out.println(pair2.getClass() == pair4.getClass());

    }
  •  泛型是在创建时声明,如果不声明,就会按照object类型来处理;
  •  泛型不支持基本数据类型;

  • 泛型类的继承
  1. 子类是泛型类,子类和父类的泛型类型要一致
  2. 子类不是泛型类,父类要明确泛型的数据类型
  3. 例如
  • 父类
public class Parent<E> {
    private E value;

    public E getValue() {
        return value;
    }

    public void setValue(E value) {
        this.value = value;
    }
}
  •  子类一(同父类一样依然是泛型)
/**
 * 泛型类派生子类,子类也是泛型类,那么子类的泛型标识要和父类一致。
 * @param <T>
 */
public class ChildFirst<T> extends Parent<T> {
    @Override
    public T getValue() {
        return super.getValue();
    }
}
  • 子类二(声明类型) 

/**
 * 泛型类派生子类,如果子类不是泛型类,那么父类要明确数据类型
 */
public class ChildSecond extends Parent<Integer> {
    @Override
    public Integer getValue() {
        return super.getValue();
    }

    @Override
    public void setValue(Integer value) {
        super.setValue(value);
    }
}
  • 他们的使用
public class Test02 {
    public static void main(String[] args) {
        
        ChildFirst<String> childFirst = new ChildFirst<>();
        childFirst.setValue("abc");
        String value = childFirst.getValue();
        System.out.println(value);
        
        
        System.out.println("---------------------------------");
        
        
        ChildSecond childSecond = new ChildSecond();
        childSecond.setValue(100);
        Integer value1 = childSecond.getValue();
        System.out.println(value1);
    }
}

二、泛型接口

1.基本语法

interface 接口名称 <泛型标识,泛型标识,…> {
  泛型标识 方法名(); 
  .....
}
  •  例如:
/**
 * 泛型接口
 * @param <T>
 */
public interface Generator<T> {
    T getKey();
}
  • 实现类不是泛型类,接口要明确数据类型
/**
 * 实现泛型接口的类,不是泛型类,需要明确实现泛型接口的数据类型。
 */
public class Apple implements Generator<String> {
    @Override
    public String getKey() {
        return "hello generic";
    }
}
  •  实现类也是泛型类,实现类和接口的泛型类型要一致

/**
 * 泛型接口的实现类,是一个泛型类,那么要保证实现接口的泛型类泛型标识包含泛型接口的泛型标识
 * @param <T>
 * @param <E>
 */
public class Pair<T,E> implements Generator<T> {

    private T key;
    private E value;

    public Pair(T key, E value) {
        this.key = key;
        this.value = value;
    }

    @Override
    public T getKey() {
        return key;
    }

    public E getValue() {
        return value;
    }
}
  •  然后就是泛型接口的使用
/**
 * 泛型接口
 */
public class Test03 {
    public static void main(String[] args) {
        Apple apple = new Apple();
        String key = apple.getKey();
        System.out.println(key);

        System.out.println("---------------------------------");
        Pair<String, Integer> pair =  new Pair<>("count",100);
        String key1 = pair.getKey();
        Integer value = pair.getValue();
        System.out.println(key1 + "=" + value);
    }
}


三、泛型方法

1.概述

  1. 重点以及难点来了,泛型方法
  2. 首先泛型方法的语法
修饰符 <T,E, ...> 返回值类型 方法名(形参列表) {
    方法体...
}
  •  例子
public class Demo01 {
    private static Random random = new Random();

    //非静态  单一泛型 有返回值
    public <T> T trans_01(List<T> list){
        return list.get(random.nextInt(4));
    }

    //非静态  单一泛型 无返回值
    public <T> void trans_02(List<T> list){
        list.forEach(x->{
            System.out.println(x);
        });
    }

    //非静态 多泛型 有返回值
    public <T,E> T trans_03(List<T> tList,List<E> eList){
        tList.addAll((Collection<? extends T>) eList);
        return tList.get(random.nextInt(6));
    }

    //非静态 多泛型 无返回值
    public <T,E> void trans_04(List<T> tList,List<E> eList){
        tList.forEach(t-> System.out.println(t));
        eList.forEach(e-> System.out.println(e));
    }

    //可变参数
    public <T> List<T> trans_05(T... param){
        return Arrays.asList(param);
    }

}

class Demo02{

    private static Random random = new Random();

    //静态 单泛型  无返回值
    public static <E> void trans_06(List<E> eList){
        eList.forEach(e->{
            System.out.println(e);
        });
    }
    //静态 多泛型 有返回值
    public static <T,E> T trans_07(List<T> tList,List<E> eList){
        tList.addAll((Collection<? extends T>) eList);
        return tList.get(random.nextInt(6));
    }

}
  • 然后就是它们的使用
class Demo03{
    public static void main(String[] args) {
        //数据准备
        Demo01 demo01 = new Demo01();
        List<String> list1 = Arrays.asList("a","b","c","d","e");
        List<Integer> list2 = Arrays.asList(1,2,3,4,5,6);
        String[] strs = {"a","b","c","d","e"};

        String trans01 = demo01.trans_01(list1);
        demo01.trans_02(list1);
        String trans03 = demo01.trans_03(list1, list2);
        demo01.trans_04(list1,list2);
        demo01.trans_05(strs);
        Demo02.trans_06(list1);
        Demo02.trans_07(list1,list2);
    }
}

 2.难点及易混点解答

  • 首先上面已经把泛型方法所涉及的出现情况涵盖了,下面将引用简单的例子将问题说清楚
  • 根据泛型方法的语法,泛型方法前必须有尖括号包含的通配符<T,E,K,V>如下:
    public <T,E> T trans_03(List<T> tList,List<E> eList){
        tList.addAll((Collection<? extends T>) eList);
        return tList.get(random.nextInt(6));
    }

    public static <T,E,K> void printType(T t, E e, K k) {
        System.out.println(t + "\t" + t.getClass().getSimpleName());
        System.out.println(e + "\t" + e.getClass().getSimpleName());
        System.out.println(k + "\t" + k.getClass().getSimpleName());
    }
  •  也就是说没有尖括号包括的通配符修饰的方法,就不是泛型方法,如下:
public class Demo01<T,K> {

    public T test_01(List<T> tList,List<K> kList){
        tList.addAll((Collection<? extends T>) kList);
        return tList.get(0);
    }

    public void test_02(List<T> tList){
        tList.forEach(t->{
            System.out.println(t);
        });
    }
}

使用如下:

public class Test01 {

    @Test
    public void test_01(){

        Demo01<String,Integer> demo01 =  new Demo01<>();
        List<String> list1 = Arrays.asList("a","b","c","d","e");
        List<Integer> list2 = Arrays.asList(1,2,3,4,5,6);

        String test01 = demo01.test_01(list1, list2);
        demo01.test_02(list1);
        
    }
}
  •  上面的方法就不是泛型方法,仅仅是使用了类泛型的普通方法,他们的泛型是严格和类的泛型一样的,比如test_01的T就必须和类的泛型T一致
  • 但是包含泛型方法的类,不一定是泛型类,如下:
public class Demo01 {
    private static Random random = new Random();

    //非静态  单一泛型 有返回值
    public <T> T trans_01(List<T> list) {
        return list.get(random.nextInt(4));
    }

}
  •  并且泛型方法的泛型是独立于类的,也就是说即使泛型方法和类的泛型都是T,也是不一样的,如下:
public class Demo01<T,K> {

    public <T, K> T test_03(List<T> tList, List<K> kList) {
        tList.addAll((Collection<? extends T>) kList);
        return tList.get(0);
    }

    public T test_01(List<T> tList,List<K> kList){
        tList.addAll((Collection<? extends T>) kList);
        return tList.get(0);
    }

    public void test_02(List<T> tList){
        tList.forEach(t->{
            System.out.println(t);
        });
    }
}

它的使用

public class Test01 {

    @Test
    public void test_01(){

        Demo01<String,Integer> demo01 =  new Demo01<>();

        List<String> list1 = Arrays.asList("a","b","c","d","e");
        List<Integer> list2 = Arrays.asList(1,2,3,4,5,6);

        List<Boolean> list3 = Arrays.asList(true,false,false,true);
        List<Double> list4 = Arrays.asList(5.22,2.33,5.66);


        //和类泛型一致
        String test01 = demo01.test_01(list1, list2);
        demo01.test_02(list1);

        //和类泛型不一致
        String test11 = demo01.test_01(list3, list4);
        demo01.test_02(list3);
        Boolean aBoolean = demo01.test_03(list3, list4);
        
    }
}

可以看到,只有使用了泛型类的test_03能使用和类的泛型不一样的类型

 

关于通配符的使用见下一节


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

PH = 7

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值