------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------
其实在之前的集合博客里面我已经大概的说了一下泛型,但是感觉泛型还是很重要的,所以就单独写了一篇
- 泛型概述:
泛型是JDK1.5中一个最重要的特征。通过引入泛型,我们将获得编译时类型的安全和运行时更小的抛出ClassCastException的可能。
在JDK1.5中,你可以声明一个集合将接收/返回的对象的类型。
使用泛型时如果不指明参数类型,即泛型类没有参数化,会提示警告,此时类型为Object。
- 泛型基础:
尖括号中包含的是形式类型参数(formal type parameters),它们就如同一般的类型一样,可以在整个类的声明中被使用。
当类被使用时,会使用具体的实际类型参数(actual type argument)代替。
比如前面的例子中的List<Integer>,那么所有的E将会被Integer类型所代替。
泛型类型参数只能被类或接口类型赋值,不能被原生数据类型赋值,原生数据类型需要使用对应的包装类。
形式类型参数的命名:尽量使用单个的大写字母(有时候多个泛型类型时会加上数字,比如T1,T2),比如许多容器集合使用E,代表element(元素),Map中用K代表键keys,V代表值
- 泛型详解:
1.泛型类被所有其实例(instances)共享的另一个暗示是检查一个实例是不是一个特定类型的泛型类是没有意义的。
Collection cs = new ArrayList<String>();if (cs instanceof Collection<String>) { ...} // 非法
类似的,如下的类型转换
Collection<String> cstr = (Collection<String>) cs;
得到一个unchecked warning,因为运行时环境不会为你作这样的检查。
2.数组范型
可以使用带范型参数值的类声明数组,却不可有创建数组List<Integer>[] iListArray;
new ArrayList<Integer>[10];//编译时错误
3.通配符
在上面两小节中,对是类型参数赋予具体的值,除此,还可以对类型参数赋予不确定值。例如List<?> unknownList;
List<? extends Number> unknownNumberList;
List<? super Integer> unknownBaseLineIntgerList;
注意: 在Java集合框架中,对于参数值是未知类型的容器类,只能读取其中元素,不能像其中添加元素,
因为,其类型是未知,所以编译器无法识别添加元素的类型和容器的类型是否兼容,唯一的例外是NULL
List<String> listString;
List<?> unknownList2 = listString;
unknownList = unknownList2;
listString = unknownList;//编译错误
4.对带类型参数方法进行赋值
当调用范型方法时,编译器自动对类型参数进行赋值,当不能成功赋值时报编译错误。例如public <T> T testGenericMethodDefine3(T t, List<T> list){
...
}
public <T> T testGenericMethodDefine4(List<T> list1, List<T> list2){
...
}
Number n = null;
Integer i = null;
Object o = null;
testGenericMethodDefine(n, i);//此时T为Number, S为Integer
testGenericMethodDefine(o, i);//T为Object, S为Integer
List<Number> list1 = null;
testGenericMethodDefine3(i, list1)//此时T为Number
List<Integer> list2 = null;
testGenericMethodDefine4(list1, list2)//编译报错
5.为了保证代码的兼容性,下面的代码编译器(javac)允许,类型安全有你自己保证
List l = new ArrayList<String>();List<String> l = new ArrayList();
- 泛型实例:
package fanxing;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
public class FanXing {
public static void main(String[] args) throws Exception {
List list = new ArrayList();
list.add(1);
list.add(5);
int num = (Integer) list.get(1);
//System.out.println(num);
ArrayList<Integer> list2 = new ArrayList<Integer>();
list2.getClass().getMethod("add", Object.class).invoke(list2, 1);
//System.out.println(list2.get(0));
//System.out.println(Arrays.asList(show(new String[]{"a","b","c"}, 0, 1)));
Number x = add(1.5,5);
Object obj = add(1,"a");//编译时期检查不出,必须要运算结果出来才能有错误显示
//通过反射的参数的实际参数
Method method = FanXing.class.getMethod("fors", List.class);
Type[] types = method.getGenericParameterTypes();//得到方法的形式参数
ParameterizedType pt = (ParameterizedType) types[0];
System.out.println(pt.getActualTypeArguments()[0]);//得到形式参数的实际参数
System.out.println(pt.getRawType());//得到此类型的类和接口
}
public void fors(List<String> list){
}
public static<T> void copy(Collection<T> collection, T[] arr){
}
//T只能接受对象类型,调换数组坐标的位置
public static <T> T[] show(T[] arr, int x, int y){
T t = arr[x];
arr[x] = arr[y];
arr[y] = t;
return arr;
}
public static <T> T add(T x, T y){
return null;
}
}