[改善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);
}
}
如果你期望生成的列表长度是可变的,那就需要自己来写一个数组的工具类了.代码如下:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List; public class Client { public static void main(String[] args) {
//正规用法
List<String> list1 = ArrayUtils.asList("A","B");
//参数为空
List list2 = ArrayUtils.asList();
//参数为数字和字符串的混合
List list3 = ArrayUtils.asList(1,2,3.1);
} } class ArrayUtils{
//把一个变长参数转变为列表
public static <T> List<T> asList(T...t){
List<T> list = new ArrayList<T>();
Collections.addAll(list, t);
return list;
}
}
与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>类型了.
什么时候明确泛型类型呢?
一句话:无法从代码中推断出泛型类型的情况下,即可强制声明泛型类型.
[改善Java代码]强制声明泛型的实际类型的更多相关文章
- [改善Java代码]不能初始化泛型参数和数组
泛型类型在编译期被擦除,我们在类初始化时将无法获得泛型的具体参数,比如这样的代码: class Foo<T>{ //private T t =new T();//报错Cannot inst ...
- [改善Java代码]Java的泛型是类型擦除的
泛型可以减少强制类型的转换,可规范集合的元素类型,还可以提高代码的安全性和可读性,正是因为有了这些优点,自从Java引入泛型之后,项目的编码规则上便多了一条,优先使用泛型. Java泛型(Generi ...
- [改善Java代码]数组的真实类型必须是泛型类型的子类型
List接口的toArray方法可以把一个结合转化为数组,但是使用不方便,toArray()方法返回的是一个Object数组,所以需要自行转变. toArray(T[] a)虽然返回的是T类型的数组, ...
- [改善Java代码]易变业务使用脚本语言编写
建议16: 易变业务使用脚本语言编写 Java世界一直在遭受着异种语言的入侵,比如PHP.Ruby.Groovy.JavaScript等,这些“入侵者”都有一个共同特征:全是同一类语言—脚本语言,它们 ...
- [改善Java代码]用枚举实现工厂方法模式更简洁
工厂方法模式(Factory Method Patter)是"创建对象的接口",让子类决定实例化哪一个类,并使一个类的实例化延迟到其子类.工厂方法模式在我们的开发工作中,经常会用到 ...
- Java进阶(四)Java反射TypeToken解决泛型运行时类型擦除问题
在开发时,遇到了下面这条语句,不懂,然习之. private List<MyZhuiHaoDetailModel> listLottery = new ArrayList<MyZhu ...
- [改善Java代码]警惕泛型是不能协变和逆变的
什么叫做协变(covariance)和逆变(contravariance)? 在变成语言的类型框架中,协变和逆变是指宽类型和窄类型在某种情况下(如参数,泛型,返回值)替换或交换的特性,简单的说,协变是 ...
- [改善Java代码]不同的场景使用不同的泛型通配符
Java泛型支持通配符(Wildcard),可以单独使用一个"?"表示任意类,也可以使用extends关键字标识某一类(接口)的子类型,还可以使用super关键字标识某一类(接口) ...
- [改善Java代码]静态变量一定要先声明后赋值
建议32: 静态变量一定要先声明后赋值 这标题看着让人很纳闷,什么叫做变量一定要先声明后赋值?Java中的变量不都是先声明后使用的吗?难道还能先使用后声明?能不能暂且不说,我们先来看一个例子,代码如下 ...
随机推荐
- 第二百三十九天 how can I 坚持
去看了个电影,消失的凶手,乐视会员送的电影票,有点虐心,不过看着感觉还挺不错. 下了班就去看了,也没有吃饭,不过没感觉到饿,回来吃了份泡面,还喝了袋冰凉的酸奶,现在已经感觉肚子有点疼了,哎.. 哲学是 ...
- Hibernate关联关系之双向1—n
•双向 1-n 与双向 n-1 是完全相同的两种情形 •双向 1-n 需要在1的一端可以访问n的一端,反之依然. 测试实例代码: 实体类: package com.elgin.hibernate.nt ...
- Spring Auto proxy creator example
In last Spring AOP examples – advice, pointcut and advisor, you have to manually create a proxy bean ...
- HDU2066一个人的旅行(dijkstra)
一开始拿到这个题感觉floyd可能会超,还是写了写,果然1WA+1TLE,之后觉得用dijkstra试试看看S和D会不会比较小,还是1WA+1TLE,最后还是借鉴了别人的做法. 把他的家作为起点,与他 ...
- Unity3D之Legacy动画系统学习笔记
Unity3D的Mecanim动画系统是非常强大的,而且作为Unity推荐的动画系统,其未来会完全代替老的一套动画系统,即Legacy动画系统.目前的情况是Mecanim与Legacy两套动画系统同时 ...
- ASP.NET- 使用NPOI导入导出标准Excel
尝试过很多Excel导入导出方法,都不太理想,无意中逛到oschina时,发现了NPOI,无需Office COM组件且不依赖Office,顿时惊为天人,怀着无比激动的心情写下此文. 曾使用过的方法 ...
- PicklingError: Can't pickle <type 'generator'>: it's not found as __builtin_
多进程传递 参数时,需要是python系统已知的,不然不知道怎么序列化
- disque概要
做项目过程接触到disque,记录一下. disque是redis之父开源的基于内存的分布式作业队列,用c语言实现的非阻塞网络服务器. disque的设计目标:Its goal is to captu ...
- UVa784 Maze Exploration
// 题意:输入一个迷宫,从*开始遍历,把可达点标记为字符# 注意迷宫边界不规则,要用strlen判断. #include<cstdio> #include<cstring> ...
- 硝烟中的scrum学习笔记 - 怎样制定Sprint计划(Plan Meeting)
1. 如何估算我们这个sprint能做多少个故事点 1) 本能反应 2) 生产率计算 估算生产率/实际生产率 看看团队的历史,看看他们在过去几个sprint里的生产率是多少 然后假定在下一个sp ...