java泛型的了解
java泛型是1.5的新特性,我们先通过一个例子来简单了解一下泛型。
泛型了解:
//在java 1.5之前,集合是这样处理的。List c1 = new ArrayList();c1.add("abc");c1.add(1);String s1 = (String) c1.get(0);String s2 = (String) c1.get(1);
//在java 1.5之后List<String> c1 = new ArrayList<String>();c1.add("abc");c1.add(1);
进一步了解泛型:
泛型的一些术语介绍:
ArrayList<E> ArrayList<String>
整个ArrayList<E>称为泛型类型。中间这个<E>称为类型变量,(类型参数)
整个ArrayList<String>称为参数化的类型,String称为实际类型参数或者类型参数的实例。
ArrayList称为原始类型。
泛型的一些思考:
一:
List<String> c1 = new ArrayList<String>();List<Integer> c2 = new ArrayList<Integer>();System.out.println(c1.getClass() == c2.getClass());
true
既然,字节码中已经没有了类型信息的限制,那通过反射,就可以往集合中放入其它类型的实例了。看一下如下代码:
List<String> c1 = new ArrayList<String>();try {Method method = c1.getClass().getMethod("add", Object.class);method.invoke(c1, 123);Object object = c1.get(0);System.out.println(object);} catch (Exception e) {e.printStackTrace();}
123
二:
参数化类型和原始类型的兼容性:
//可以编译通过List<String> c1 = new ArrayList();//可以编译通过List c2 = new ArrayList<String>();//不可以编译通过List<String> c3 = new ArrayList<Object>();//不可以编译通过List<Object> c3 = new ArrayList<String>();
泛型的通配符:
在api文档中,经常会看到这样的“<?>”这样的问号在类的后面跟着。先通过一个需求来了解问号。
定义一个方法,可以打印任意List集合中的元素。(List<Integer>,List<String>......)这样的参数化类型都可以打印。
public void print(List<?> list){for (Object object : list) {System.out.println(object);}}
public void method1(Collection<Object> c){//可以编译通过,add的是Objectc.add("abc");c.add(123);//错误,前面说过,参数化类型是不考虑继承的。所以,错误c = new ArrayList<String>();}public void method2(Collection<?> c){//并没有声明具体类型就放String?错误c.add("abc");//把一个?(可以匹配任意类型),让它类型参数实例为Stringc = new ArrayList<String>();}
List<? extends Number> list = new ArrayList<Integer>();
//正确List<? super Integer> list1 = new ArrayList<Number>();//错误List<? super Integer> list2 = new ArrayList<String>();
//正确,可以把一个类型给?List<?> list1 = new ArrayList<Number>();//错误,不可以把一个?给一个具体类型List<Number> list2 = new ArrayList<?>();
自定义泛型:
java的泛型是从c++泛型借鉴过来的,但没有c++的强大,但java还是尽可能的去模仿c++的泛型。
同样,看一个需求,写一个方法,可以实现2个数的相加,但类型不同,先看看c++的实现
template<class T>T add(T x,T y){return (T)x+y;}
/*** 如何定义一个类型,返回值之前,并紧挨着返回值。*/public <T> T add(T x,T y){// The operator + is undefined for the argument type(s) T, T// 对于T来说,可能没有+这个操作。因此,在java中不能实现c++这样的功能,但仍然了解了java中泛型在方法上的使用。// return (T)x+y;return null;}
泛型的类型推断:
在上面的add方法中,尝试着这样的调用。
add(1, 2);add(1, 2.0);add(1, "abc");
Integer add = add(1, 2);Number add2 = add(1, 2.0);Object add3 = add(1, "abc");
public static <T> void copy(Collection<T> c,T[] a) {}//错误copy(new ArrayList<Float>(), new Integer[10]);
自定义泛型方法&自定义泛型类
1:自定义泛型方法。如上面的add方法一样。
例子:写一个方法,可以交换一个数组中的2个位置上的值。
public static <T> void swap(T[] arr,int x,int y){T temp = arr[x];arr[x] = arr[y];arr[y] = temp;}
//正确swap(new String[]{"aaa","bbb"},0, 1);swap(new Integer[]{111,222},0, 1);//错误swap(new int[]{1,2}, 0, 1);
//正确ArrayList[] a1 = new ArrayList[10];//错误:Cannot create a generic array of ArrayList<String>ArrayList<String>[] a2 = new ArrayList<String>[10];
public static <T extends Exception> void method() throws T{try {} catch (Exception e) {throw (T)e;}}
public class GenericStudy<T> {}
获取类型参数实例:
由于泛型的去类型化,在编译成字节码后已经看不到这个到底是什么类型了?如何获取?
public void apply(List<String> l){}try {Method method = GenericStudy.class.getMethod("apply", List.class);Type[] genericParameterTypes = method.getGenericParameterTypes();ParameterizedType parameterizedType = (ParameterizedType) genericParameterTypes[0];Type type = parameterizedType.getActualTypeArguments()[0];Type rawType = parameterizedType.getRawType();System.out.println(rawType+":"+type);} catch (Exception e) {e.printStackTrace();}}
interface java.util.List:class java.lang.String
本文深入浅出地介绍了Java泛型的基础知识,包括泛型的引入背景、泛型的基本语法、泛型的类型擦除特性、通配符的使用以及自定义泛型方法和类等内容。此外,还探讨了泛型在实际开发中的应用案例。
10万+

被折叠的 条评论
为什么被折叠?



