java特性-泛型
1:泛型1.1 list中使用类型安全
定义A:List
尖括号中的类型必须是Object,不能是int等原始类型;一旦list被定义了特定的类型,那么使用add方法时,放入list的对象必定是你定义list时的类型对象
定义B: List
可以添加子类对象:list.add(new Integer(1))或list.add(new Float(2))
1.2 map中使用类型安全
定义:
1 2 3 4 | Map<Integer, Integer> mapA = new HashMap<Integer, Integer>(); Map<String, String> mapB = new HashMap<String, String>(); Map<String, Object> mapC = new HashMap<String, Object>(); Map<Long, String> mapD = new HashMap<Long, String>(); |
1.3 Iterating Over Parameterized Types
看一下代码A
1 2 3 4 5 6 7 8 | List<String> list = new LinkedList( ); list.add("hello"); list.add("world"); //for (Iterator i = list.iterator( ); i.hasNext(); ) { for (Iterator<String> i = list.iterator(); i.hasNext(); ) { String s = i.next(); System.out.println(s); } |
如果for语句的定义是注释那句的话,编译报错;如果之前的collections是参数化的,那么这里的iterator必须也要参数化.
看一下代码B
1 2 3 4 5 6 7 8 | List list = new LinkedList( ); list.add("hello"); list.add("world"); list.add(1); for (Iterator<String> i = list.iterator(); i.hasNext(); ) { String s = i.next(); System.out.println(s); } |
以上代码虽然在编译期通过,但在运行期发生严重的错误:java.lang.ClassCastException,所以如果你想使用参数化的iterator,那么你就要参数化你的collections
1.4 Accepting Parameterized Types as Arguments
看一下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 | public static void main(String[] args) { List list = new LinkedList( ); list.add("hello"); list.add("world"); list.add(1); printListOfString(list); } public static void printListOfString(List<String> list) { for(Iterator<String> iterator = list.iterator();iterator.hasNext();) { System.out.println(iterator.next()); } } |
编译时没有错误,运行时报ClassCastException,所以调用类型安全的方法时,确保你传入的parameter是类型安全的.例子中传入的list最好申明为:List
1.5 Returning Parameterized Types
看一下代码
1 2 3 4 5 6 7 8 9 10 11 | public static void main(String[] args) { List list = getListOfStrings(); //List<String> list = getListOfStrings(); } public static List<String> getListOfStrings() { List<String> list = new LinkedList<String>(); list.add("Hello"); list.add("World"); return list; } |
1.6 Using Parameterized Types as Type Parameters
看一下代码
1 2 3 | Map<String, List<String>> mapA = new HashMap<String, List<String>>(); Map<String, List<List<int[]>>> mapB; Map<String, List<int[]>> mapC; |
注意mapB和mapC的区别
1.7 Generics and Type Conversions
看一下代码A:
1 2 3 | LinkedList<Float> floatList = new LinkedList<Float>(); List<Float> moreFloats = floatList; //正确的转换 LinkedList<Number> numberList = floatList; //错误的转换 |
这个错误我也看了好久才明白:
1:类型转换只允许基础类,而不是类型安全所申明的类,这也是为了防止运行期的错误
2:类型安全是在编译期做处理,做类型安全的检查,一定编译通过,真正的代码将是没有类型安全定义的,如:
List
在编译后就成:
List floatList = new LinkedList();
所以只做基础类别List的转换比parameter type的转换更合理
看一下代码B:
1 2 3 4 | List<Integer> ints = new LinkedList<Integer>(); List oldList = ints; oldList.add("Hello World"); Integer i = ints.get(0); |
这里ints转成了无类型定义的list,虽然编译通过,但是runtime时发生ClassCastException,反编译.class文件看到:
1 2 3 4 | List ints = new LinkedList(); List oldList = ints; oldList.add("Hello World"); Integer i = (Integer)ints.get(0); |
从上而知:所谓类型安全自是为了开发者方便,容易检查错误,在编译后,运行时,jvm自动帮助做了类型转换
1.8 Using Type Wildcards
看一下代码
1 2 3 4 5 6 7 8 9 10 11 12 | public static void main(String[] args) { List<TypeWildcards> list = new ArrayList<TypeWildcards>(); TypeWildcards a = new TypeWildcards(); list.add(a); printList(list); } public static void printList(List<?> list){ for (Iterator<?> i = list.iterator(); i.hasNext();) { System.out.println(i.next().toString()); } } |
1.9 Writing Generic Types
看一下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | import java.util.ArrayList; import java.util.List; public class Box<A> { public static void main(String[] args) { Box<Integer> box = new Box<Integer>(); box.add(1); } protected List<A> contents; public Box(){ contents = new ArrayList<A>(); } public int getSize() { return contents.size(); } public boolean isEmpty() { return (contents.size() == 0); } public void add(A o) { contents.add(o); } public A grab() { if (!isEmpty()) { return contents.remove(0); } else { return null; } } } |
代码中的A可以是其他的英文字符,大小写均可
1.10 Restricting Type Parameters
看一下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 | import java.util.Iterator; public class NumberBox<A extends Number> extends Box<A> { public NumberBox(){ super(); } public double sum() { double total = 0; for (Iterator<A> i = contents.iterator(); i.hasNext();) { total = total + i.next().doubleValue(); } return total; } } |