zoukankan      html  css  js  c++  java
  • [改善Java代码]强制声明泛型的实际类型

    Arrays工具类有一个方法asList可以把一个变长参数或数组变成列表,但是它有一个缺点:它所生成的List长度是不可改变的,而这在我们的项目开发中很不方便.

    import java.util.Arrays;
    import java.util.List;
    
    public class Client {
        public static void main(String[] args) {
            String[] strArray = {"1","18","71","61","51"};
            List<String> asList = Arrays.asList(strArray);
            //asList.add("tttt");//会在这一行报错:Exception in thread "main" java.lang.UnsupportedOperationException
            System.out.println(asList);
        }
    }

    如果你期望生成的列表长度是可变的,那就需要自己来写一个数组的工具类了.代码如下:

     1 import java.util.ArrayList;
     2 import java.util.Collections;
     3 import java.util.List;
     4 
     5 public class Client {
     6     
     7     public static void main(String[] args) {
     8         //正规用法
     9         List<String> list1 = ArrayUtils.asList("A","B");
    10         //参数为空
    11         List list2 = ArrayUtils.asList();
    12         //参数为数字和字符串的混合
    13         List list3 = ArrayUtils.asList(1,2,3.1);
    14     }
    15     
    16 
    17 }
    18 
    19 class ArrayUtils{
    20     //把一个变长参数转变为列表
    21     public  static <T> List<T> asList(T...t){
    22         List<T> list = new ArrayList<T>();
    23         Collections.addAll(list, t);
    24         return list;
    25     }
    26 }

    与Arrays.asList的调用方式相同,我们传入一个泛型对象,然后返回相应的List.

    这里有三个变量需要说明:

    (1)变量list1

    泛型实际的参数类型是String,返回的结果也就是容纳String元素的List对象.

    (2)变量list2

    传递的是空参数,编译器也不知道泛型的实际参数类型是什么,不过编译器会认为Object就是其泛型类型,也就是说list2的完整定义如下:

    List<Object> list2 = ArrayUtils.asList();

    这样编译时就不会给出"unchecked"警告了.

    如果期望list2是一个Integer类型的列表,而不是Object列表,因为后续的逻辑会把Interger类型加入到list2中,如何处理?

    强制类型转化,把asList强制转换成List<Integer>?行不通,虽然Java的泛型是编译擦除式的,但是List<Object>和List<Intger>没有继承关系,不能进行强制转换.

    最好的解决办法是强制声明泛型类型,代码如下:

    List<Integer> list22 = ArrayUtils.<Integer>asList();

    asList方法要求的是一个泛型参数,那我们就在输入前定义这是一个Integer类型的参数,当然,输出也是Integer类型的集合了.

    (3)变量list3

    变量list3有两种类型的元素:整数类型和浮点类型,那它生成的List泛型化参数应该是什么呢?

    Integer和Float的父类Number?你太高看编译器了,它不会如此的推断的,当它发现多个元素的实际类型不一致的时候就会直接确认泛型类型是Object.而不会去追查元素类的公共父类是什么,但是对于list3,我们更期望它的泛型参数是Number.参照list2变量,代码修改如下:

    List<Number> list33 = ArrayUtils.<Number>asList(1,2,3.1);

    Number是Integer和Float的父类,先把三个输入参数向上转型为Number,那么返回的结果也就是List<Number>类型了.

    什么时候明确泛型类型呢?

    一句话:无法从代码中推断出泛型类型的情况下,即可强制声明泛型类型.

  • 相关阅读:
    Kettle 实现mysql数据库不同表之间数据同步——实验过程
    Kettle ETL 来进行mysql 数据同步——试验环境搭建(表中无索引,无约束,无外键连接的情况)
    并查集知识总结
    c# 线程同步问题(about volatile)
    c# 线程的等待(堵塞)
    net中多线程返回值
    c# 中的 lock monitor mutex Semaphore 的比较
    c#两种同步结构
    links-some-blog
    T-SQL中的APPLY用法
  • 原文地址:https://www.cnblogs.com/DreamDrive/p/5624171.html
Copyright © 2011-2022 走看看