泛型 Generic
标签
把元素的类型设计成一个参数,这个类型参数叫做泛型。Collection ; List; ArrayList; 这个 就是泛型
jdk 1.5 新增特性
// TAKE ArrayList AS EXAMPLE
package com.generic;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Iterator;
// generic
public class Demo00 {
// before Collection use generic
@Test
public void test(){
ArrayList list = new ArrayList();
// demand: store students' score
list.add(45);
list.add(56);
list.add(77);
// problem 1 : data type not safe
// list.add("tom");
for(Object score:list){
// problem 2 : may cause ClassCastException when force cast
int stuScore = (Integer)score; // object --> int
System.out.println(stuScore);
}
}
// use generic in Collection
// generic is an type, cannot be primary data type(like int)
// check the data type during compiling to ensure data security
@Test
public void test1(){
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(56);
list.add(76);
list.add(99);
// list.add("tom"); compile not pass
// 1.
for(Integer score:list){
// avoid force cast
int stuScore = score;
System.out.println(stuScore);
}
// 2.
Iterator<Integer> iterator = list.iterator();
while(iterator.hasNext()){
int stuScore = iterator.next();
System.out.println(stuScore);
}
}
}
// TAKE HashMap AS EXAMPLE
@Test
public void test2(){
Map<String,Integer> map = new HashMap<String, Integer>();
map.put("joe",23);
map.put("tom",78);
map.put("jerry",8);
// nested generic
Set<Map.Entry<String,Integer>> entry = map.entrySet();
Iterator<Map.Entry<String,Integer>> iterator = entry.iterator();
while(iterator.hasNext()){
Map.Entry<String,Integer> entry1 = iterator.next();
String key = entry1.getKey();
Integer value = entry1.getValue();
System.out.println(key+"--"+value);
}
}
在集合中使用泛型
- 集合接口或集合类在 jdk 5.0 之后都修改为带泛型的结构
- 在实例化集合类时,可以指明具体的泛型类型
- 指明完以后,在集合类或接口中凡是定义类或接口时,内部结构(比如:方法、构造器、属性等)使用到类的泛型的位置,都指定为实例化的类型。比如:add(E e) 实例化以后:add(Integer e)
- 注意:泛型的类型必须是类,不能是基本数据类型。需要用到基本数据类型的位置,拿包装类进行替换
- 如果实例化时,没有指明泛型的类型。默认为 java.lang.Object 类型
- jdk 7 中可进行类型推断,后面不必写泛型
practice:generic - practice 对比 set - practice
使用泛型之前与使用泛型之后
自定义泛型结构
泛型类|泛型接口|泛型方法
自定义泛型类/接口
package com.generic;
import com.generic.practice.SubOrder;
import com.generic.practice.SubOrder1;
import org.junit.Test;
// custom generic class
public class Order<T> { // T: generic of class
String orderName;
int orderID;
// The inner structure of class can use class's generic
T orderT;
public Order() {
}
public Order(String orderName, int orderID, T orderT) {
this.orderName = orderName;
this.orderID = orderID;
this.orderT = orderT;
}
public T getOrderT(){
return orderT;
}
public void setOrderT(T orderT){
this.orderT = orderT;
}
@Override
public String toString() {
return "Demo01{" +
"orderName='" + orderName + '\'' +
", orderID=" + orderID +
", orderT=" + orderT +
'}';
}
@Test
public void test2(){
SubOrder sub1 = new SubOrder();
// 由于子类在继承带泛型的父类时,指明了泛型类型
// 则实例化子类对象时,不再需要指明泛型
sub1.setOrderT(123);
SubOrder1<String> sub2 = new SubOrder1<>();
sub2.setOrderT("order2...");
}
}
package com.generic.practice;
import com.generic.Order;
public class SubOrder extends Order<Integer> {
}
package com.generic.practice;
import com.generic.Order;
public class SubOrder1<T> extends Order<T> {
// SubOrder1<T>:仍然是泛型类
}
注意点
-
泛型类可能有多个泛型参数
-
泛型类的构造器:public GenericClass(){}
-
实例化后操作原来泛型位置的结构必须与指定的泛型类型一致
-
泛型不同的引用不能相互赋值
package com.generic; import java.util.ArrayList; // 泛型不同的引用不能相互赋值 public class Demo03 { ArrayList<String> list1 = null; ArrayList<Integer> list2 = null; // list1 = list2; Cannot do this! }
-
类型推断
-
静态方法中不能使用类的泛型
-
异常类不能声明为泛型类
-
不能使用 new E()
public Order() { // 编译不通过 // T[] arr = new T[10]; T[] arr = (T[]) new Object[10]; // 实际赋值应该为 T 或 T 的子类对象 }
-
父类有泛型,子类可以选择保留也可以选择指定泛型类型
- 子类不保留父类泛型:按需实现
- 保留:全部/部分保留
class Father<T1,T2>{ } // 子类不保留父类的类型 // 1 没有类型 擦除 class Son1 extends Father{ // 等价于 class Son extends Father<Object,Object>{} } // 2 具体类型 class Son2 extends Father<Integer,String>{ } // 子类保留父类的泛型 // 1 全部保留 class Son3<T1,T2> extends Father<T1,T2>{} // 2 部分保留 class Son4<T2> extends Father<Integer,T2>{}
自定义泛型方法
在方法中出现了泛型的结构,泛型参数与类的泛型参数没有任何关系。泛型方法所属的类是不是泛型类都没有关系。
泛型方法,可以声明为静态的。
原因:泛型参数是调用方法时确定的,并非在实例化类时确定。
public class Order<T> {
public <E> List<E> copyFromArrayToList(E[] arr){
ArrayList<E> list = new ArrayList<>();
for(E e:arr){
list.add(e);
}
return list;
}
}
package com.generic;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
public class Demo03 {
// 测试泛型方法
// 泛型方法的调用
@Test
public void test4(){
Order<String> order = new Order<String>();
Integer[] arr = new Integer[]{1,2,3,4};
// 泛型方法在调用时,指明泛型参数的类型
List<Integer> list = order.copyFromArrayToList(arr);
System.out.println(list);
}
}