泛型的使用
1.jdk 5.0新增的特性
2.在集合中使用泛型:
总结:
①集合接口或集合类在jdk 5.0时都修改为带泛型的结构
②在实例化集合类时,可以指明具体的泛型类型
③指明完以后,在集合类或接口中凡是定义类或接口时,内部结构(比如:方法、构造器、属性等)使用到类的泛型的位置,都指定为实例化的泛型类型
④注意:泛型的类型必须是类,不能是基本数据类型,需要用到基本数据类型的位置,拿包装类替换
⑤如果实例化时,没有指明泛型的类型。默认类型为java.lang.Object类型
3.常见字母泛型含义
- E - Element (在集合中使用,因为集合中存放的是元素)
- T - Type(Java 类)
- K - Key(键)
- V - Value(值)
- N - Number(数值类型)
? - 表示不确定的 java 类型 ```java public class GenericTest {
//在集合中使用泛型之前的情况 @Test public void test1(){
ArrayList list = new ArrayList();list.add(78);list.add(76);list.add(89);list.add(88);//问题一:类型不安全//list.add("Tom");for (Object score : list){//问题二:强转时,可能出现ClassCastExceptionint stuScore = (Integer) score;System.out.println(stuScore);}
}
//在集合中使用泛型的情况:Arraylist @Test public void test2(){
ArrayList<Integer> list = new ArrayList<Integer>();list.add(78);list.add(87);list.add(99);list.add(65);//编译时进行类型检查,保证数据安全//list.add("Tom");//方式一:for (Integer score : list){//避免了强转操作int stuScore = score;System.out.println(stuScore);}//方式二:Iterator<Integer> iterator = list.iterator();while (iterator.hasNext()){int stuScore = iterator.next();System.out.println(stuScore);}
}
//在集合中使用泛型的情况:HashMap @Test public void test3(){
Map<String,Integer> map = new HashMap<String,Integer>();map.put("Tom",87);map.put("Jerry",67);map.put("June",78);map.put("Gary",66);//map.put(112,"ACC");//泛型的嵌套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);}
} }
<a name="eeuLY"></a>### 自定义泛型类```javapublic class Order<T> {String orderName;int orderId;//类的内部结构就可以使用类的泛型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(){this.orderT = orderT;}@Overridepublic String toString() {return "Order{" +"orderName='" + orderName + '\'' +", orderId=" + orderId +", orderT=" + orderT +'}';}public void setOrderT(T s) {}}
public class subOrder extends Order<Integer>{}
public class GenericTest1 {@Testpublic void test1(){//如果定义了泛型类,实例化没有指明类的泛型,则认为此泛型类型为Object类型//要求:如果大家定义了类是带泛型的,建议在实例化时要指明类的泛型Order order = new Order();order.setOrderT(123);order.setOrderT("AA");//建议:实例化时指明类的泛型Order<String> order1 = new Order<String>("orderAA",1001,"orderAA");order1.setOrderT("AA:hello");}@Testpublic void test2(){subOrder sub1 = new subOrder();//由于子类在继承带泛型的父类时,指明了泛型类型。则实例化子类对象时,不再需要指明泛型sub1.setOrderT(1122);}}
注意点
1.泛型不同的引用不能相互赋值
public void test3(){ArrayList<String> list1 = null;ArrayList<Integer> list2 = new ArrayList<Integer>();//泛型不同的引用不能相互赋值//list1 = list2;People p1 = null;People p2 = null;p1 = p2;}
2.静态方法中不能使用类的泛型
public static void show(T orderT){System.out.println(orderT);}
3.异常类不能声明为泛型类
public class MyException<T> extends Exception{}public void show(){//编译不通过try{}catch(T t){}}
泛型方法
1.在方法中出现了泛型的结构,泛型参数与类的泛型参数没有任何关系,换句话说,泛型方法所属的类是不是泛型类都没有关系
2.泛型方法可以声明为静态的,原因:泛型参数是在调用方法时确定的,并非实例化时确定的
public <E> List<E> copyFromArrayToList(E[] arr){ArrayList<E> list = new ArrayList<E>();for (E e : arr){list.add(e);}return list;}
public void test4(){Order<String> order = new Order<>();Integer[] arr = new Integer[]{1,2,3,4};//泛型方法在调用时,指明泛型参数类型List<Integer> list = order.copyFromArrayToList(arr);System.out.println(list);}
泛型在继承方面的体现
public class GenericTest3 {@Testpublic void test1(){//虽然类A是类B的父类,但是G<A>和G<B>二者不具备子父类关系,二者是并列关系Object obj = null;String str = null;obj = str;Object[] arr1 = null;String[] arr2 = null;arr1 = arr2;//编译不通过/*Date date = new Date();str = date;*///此时的list1和list2的类型不具有子父类关系//编译不通过List<Object> list1 = null;List<String> list2 = null;//list1 = list2;show(list1);show1(list2);}private void show1(List<String> list2) {}private void show(List<Object> list1) {}@Testpublic void test2(){//类A是类B的父类,A<G>是B<G>的父类AbstractList<String> list1 = null;List<String> list2 = null;ArrayList<String> list3 = null;list1 = list3;list2 = list3;}}
通配符的使用
通配符:?
类A是类B的父类,G和G是没有关系的,二者共同的父类是:G<?>
public void test3(){List<Object> list1 = null;List<String> list2 = null;List<?> list = null;list = list1;list = list2;print(list1);print(list2);}public void print(List<?> list){Iterator<?> iterator = list.iterator();while(iterator.hasNext()){Object obj = iterator.next();System.out.println(obj);}}
通配符写入与读取的要求
List<String> list3 = new ArrayList<>();list3.add("AA");list3.add("BB");list3.add("CC");list = list3;//添加(写入):对于List<?>就不能向其内部添加数据//除了添加null之外//list.add("DD");//list.add('?');list.add(null);//获取(读取):允许读取数据,读取的数据类型为ObjectObject o = list.get(0);System.out.println(o);
有限制条件的通配符的使用
? extends A: G<? extends A> 可以作为G和G的父类,其中B是A的子类
? super A: G<? super A> 可以作为G和G的父类,其中B是A的父类
public void test1(){List<? extends Person> list1 = null;List<? super Person> list2 = null;List<Student> list3 = new ArrayList<Student>();List<Person> list4 = new ArrayList<Person>();List<Object> list5 = new ArrayList<Object>();list1 = list3;list1 = list4;//list1 = list5;//list2 = list3;list2 = list4;list2 = list5;}
