java 泛型的使用

泛型

为什么需要泛型

  • 看如下代码
 ArrayList list = new ArrayList();
list.add("张三");
list.add(123234);
list.add(new Object());
for (int i = 0; i < list.size(); i++) {
    Object ele = list.get(i);
    if (ele instanceof String) {
        System.out.println(list.get(i));
    }else if (ele instanceof Integer) {
        System.out.println(ele);
    }else{
        System.out.println(ele);
    }
}
/** 输出结果:
	* 张三
    * 123234
    * java.lang.Object@1b6d3586
    *
    * */
  • 从上面的代码可以看出,当我们在集合中添加数据时 集合可以存储任意类型数据, 但是取数据时非常麻烦,因为取数据时,不知道是什么类型, 所以还要进行判断,和强制转换 且很容易出现“java.lang.ClassCastException”异常。那么我们就需要约束或者指定这个集合只能存储某一个类型,这时我们就需要使用泛型。

  • JDK 1.5之后出现了新的技术 —— 泛型(Generic),此技术的最大特点是类中的属性的类型可以由外部决定。泛 型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么 参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此 时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。

ArrayList<String>  list = new ArrayList<>(); // 那么它只能存储String类型, 无法存储其他类型
list.add("张三");
list.add("李四");
list.add(1243231432); // 编译错误
for (String name : list) {
   System.out.println(name);
}

自定义泛型类

// 此时的数据类型T 就需要外部提供
class Node<T> {
    private T data;
    public Node(T data) {
        this.data = data;
    }
    public void setData(T data) {
        this.data = data;
    }

    public T getData() {
        return data;
    }
}


public class GenericityDemo {
    public static void main(String[] args) {
        // 这里<> 里面的数据类型就对应者 Node 中的T
        Node<Integer> integerNode = new Node<>(1024);
        System.out.println(integerNode.getData()); // 1024

        Node<String> stringNode = new Node<>("张三");
        System.out.println(stringNode.getData()); // 张三

    }
 }

  • 在泛型接口、泛型类和泛型方法的过程中, 我们常见的如 T、E、K、V等形式的参数常用于表示泛型形参,由于接收来自外部使用时候传入类型实参,从编码的角度也成为参数化类型
  • 泛型只作用与代码的编译阶段, 在编译的过程中, 正确的检验泛型结果后, 会擦除泛型相关的信息将实际类型进行替换, 泛型不会出现在运行阶段。

泛型通配符

  • 因为不知道调用者所传递的时什么类型泛型
  • 有可能 是 Node、Node…
  • 为了达到通用性, 我们使用通配符 ? 来进行接收任意泛型类型
public class GenericityDemo {
    public static void getData(Node<?> node) {
        System.out.println(node.getData());
    }

    public static void main(String[] args) {
        Node<Integer> integerNode = new Node<>(1024);
        Node<String> stringNode = new Node<>("张三");
        getData(integerNode); // 1024
        getData(stringNode); // 张三
        
    }
 }

泛型上限

  • 指一个操作的泛型最大操作的父类,例如: 最大上限为: Number 类型, 此时,所能够接收的类只能是Number 及其子类
  • 语法 <? extends 最大上限类>
public class GenericityDemo {
    public static void getData2(Node<? extends Number> node) {
        System.out.println(node.getData());
    }

    public static void main(String[] args) {
        Node<Integer> integerNode = new Node<>(1024);
        Node<Float> floatNode = new Node<>(3.14F);
        Node<Long> longNode = new Node<>(23452354L);
		Node<String> stringNode = new Node<> ("fawefaef");
        
        getData2(integerNode); // 1024
        getData2(floatNode); // 3.14
        getData2(longNode); // 23452354
        getData2(stringNode) // 报错
       
    }
 }

泛型下限

  • 与泛型上限相反, 只能接收具体的类 或者是父类, 例如: 最小上限为: Integer 类型, 那么它只能接收 Integer类型 和 此类的父类
  • 语法: ? super 最小上限类
public class GenericityDemo {
    public static void getData2(Node<? extends Number> node) {
        System.out.println(node.getData());
    }

    public static void main(String[] args) {
        Node<Integer> integerNode = new Node<>(1024);
        Node<Float> floatNode = new Node<>(3.14F);
      	Node<Number> numberNode = new Node<>(3423);
        
        getData3(integerNode); // 1024
        getData3(floatNode); // 编译出错
        getData3(numberNode); // 3423
       
    }
 }

泛型方法

  • 泛型除了在类中定义之外,还可以在方法上定义,而且在方法上使用泛型,此方法所在的类不一定是泛型的操作 类。
public class GenericityDemo {
    // 第一个接收的泛型类型
    // 第二个表示函数返回值
    // 第三个接收T类型的数组
   public static <T> T[] func(T[] array, int in1, int in2) {
        T temp = array[in1];
        array[in1] = array[in2];
        array[in2] = temp;
        return array;
    }

    public static void main(String[] args) {
        String[] arr = {"张三", "李四", "王五", "赵六"};
        System.out.println("交换前:" + Arrays.toString(arr)); // 交换前:[张三, 李四, 王五, 赵六]
        String[] arr2 = func(arr, 0, 1);
        System.out.println("交换后:"  + Arrays.toString(arr2)); // 交换后:[李四, 张三, 王五, 赵六]

    }
 }

泛型的嵌套

public class GenericityDemo {
    public static void main(String[] args) {
        HashMap<Integer, String> map = new HashMap<>();
        map.put(1, "张三");
        map.put(2, "李四");
        map.put(3, "王五");

        // 获取一个Entry集合
        Set<Map.Entry<Integer, String>> set = map.entrySet();
        for (Map.Entry<Integer, String> entry: set) {
            System.out.println(entry.getKey() + "-->" + entry.getValue());
        }

    }
 }

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值