泛型

    科技2022-08-27  100

    1. 为什么使用泛型

    2. 在集合中使用泛型

    package org.example; import org.junit.Test; import java.util.*; /** * 泛型的使用 * 1. jdk 5.0新增特性 * <p> * 2. 在集合中使用泛型: * 总结: * 1)集合接口或集合类在jdk5.0都修改为带泛型的结构。 * 2)在实例化集合类时,可以指明具体的泛型类型。 * 3)指明完之后,在集合接口或类中凡是定义类或接口时,内部结构使用到类的泛型的位置, * 都指定为实例化时的泛型类性 * 如:add(E e) --->实例化以后 add(Integer e) *4) 注意点:泛型的类型必须是类,不能是基本数据类型。 * 5)如果实例化时,没有指明泛型类型,默认类型为java.lang.Object. * * jdk7新特性:类型推断 * Map<String, Integer> map = new Map<>(); * * @author AmorFati * 2020/10/5 20:04 */ public class GenericTest { @Test public void test1() { //需求:存放学生成绩 ArrayList list = new ArrayList(); list.add(33); list.add(44); list.add(77); list.add(88); //问题一:类型不安全 list.add("Tom"); for (Object score : list) { //问题二:强转时,可能出现ClassCastException int stuScore = (int) score; } } //在集合中使用泛型的情况 @Test public void test2() { ArrayList<Integer> list = new ArrayList<>(); list.add(33); list.add(44); list.add(77); list.add(88); //编译时,就会进行类型检查,保证数据类型的安全 // list.add("Tom"); //方式一: for (Integer score : list) { //避免了强转操作 int stuScore = score; } //方式二: Iterator<Integer> iterator = list.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } } //在集合中使用泛型的情况,以HashMap为例 @Test public void test3() { Map<String, Integer> map = new HashMap<String, Integer>(); map.put("Tom", 88); map.put("Jack", 55); map.put("Sam", 78); map.put("Amy", 54); //泛型的嵌套 Set<Map.Entry<String, Integer>> entries = map.entrySet(); Iterator<Map.Entry<String, Integer>> iterator = entries.iterator(); while (iterator.hasNext()) { Map.Entry<String, Integer> next = iterator.next(); System.out.println(next.getKey() + "=" + next.getValue()); } } }

    3. 自定义泛型结构

    自定义泛型类或接口

    public class Order<T> { String orderName; int orderId; //类的内部结构可以使用类的泛型 T orderT; public Order() { //编译不通过 // T[] arr = new T[10]; //编译通过 T[] arr = (T[]) new Object[10]; } public Order(String orderName, int orderId, T orderT) { this.orderName = orderName; this.orderId = orderId; this.orderT = orderT; } public T getOrderT() { return orderT; } } //SubOrder不是泛型 public class SubOrder extends Order<Integer> { } //SubOrder1<T>仍然是泛型 public class SubOrder1<T> extends Order<T> { } package org.example; import org.junit.Test; import java.util.ArrayList; /** * 1. 关于自定义泛型类,泛型接口。 */ public class GenericTest1 { @Test public void test1() { //要求:如果大家定义了类是带泛型的,建议在实例化时要指明类的泛型。 Order<String> order = new Order<>(); } @Test public void test2() { //由于子类在继承带泛型的父类时,指明了泛型类型, 则实例化子类对象时,不在需要指明泛型。 SubOrder subOrder = new SubOrder(); SubOrder1<String> subOrder1 = new SubOrder1<>(); } @Test public void test3() { ArrayList<Integer> list1 = new ArrayList<>(); ArrayList<String> list2 = new ArrayList<>(); //泛型的不同引用不能相互赋值。 // list1 = list2; } }

    自定义泛型方法

    //泛型方法:在方法中出现了泛型结构,泛型参数与类的泛型参数没有任何关系 //换句话说,泛型方法所属的类是不是泛型类都没有关系 //泛型方法可以声明static //原因:泛型参数是在调用方法时确定的,并非在实例化时确定的。 public <E> List<E> copyFromArrayToList(E[] arr) { ArrayList<E> list = new ArrayList<>(); for (E e : arr) { list.add(e); } return list; } @Test public void test4() { Integer[] arr = new Integer[]{1, 2, 3, 4}; List<Integer> list = copyFromArrayToList(arr); System.out.println(list); }

    4. 泛型在继承上的体现

    package org.example.java2; import org.junit.Test; import java.util.ArrayList; import java.util.List; /** * 1. 泛型在继承方面的体现 *虽然类A是类B的父类,但是G<A>和G<B>二者不具备子父类关系,二者是并列关系。如Test1 * *类A是类B的父类,A<G>是B<G>的父类。如Test2 * * @author AmorFati * @create 2020/10/5 21:31 */ public class GenericTest { @Test public void test1() { Object[] arr1 = null; String[] arr2 = null; arr1 = arr2;//编译通过 List<Object> list1 = null; List<String> list2 = null; //此时list1和list2不具备子父类关系,编译不通过。 // list1 = list2; /* 反证法: 假设list1 = list2;成立 list1.add(123);导致混入非String的数据,出错。 */ } @Test public void test2() { List<String> list1 = null; ArrayList<String> list2 = null; list1 = list2; } }

    5. 通配符的使用

    package org.example.java2; import org.junit.Test; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * 通配符的使用 * 通配符:? (英文格式下) * <p> * 类A是类B的父类,G<A>和G<B>没有关系,二者共同的父类是G<?> * * @author AmorFati * @create 2020/10/5 21:46 */ public class GenericTest1 { @Test public void test1() { List<Object> list1 = new ArrayList<>(); List<String> list2 = new ArrayList<>(); List<?> list = null; list = list1; list = list2; List<String> list3 = new ArrayList<>(); list3.add("AA"); list3.add("BB"); list3.add("CC"); list = list3; //添加(写入),对于List<?>就不能向其内部添加数据 //除了添加null之外。 // list.add("DD");编译不通过 //获取(读取):允许读取数据,读取的数据类型为Object. Object o = list.get(0); } public void print(List<?> list) { Iterator<?> iterator = list.iterator(); while (iterator.hasNext()) { Object obj = iterator.next(); System.out.println(obj); } } }

    有限制条件的通配符

    public class Person { } public class Student extends Person { } /* 有限制条件的通配符的使用 ? extends A: G<? extends A> 可以作为G<A>和G<B>的父类,其中B是A的子类。 ? super A: G<? super A> 可以作为G<A>和G<B>的子类,其中B是A的父类。 */ @Test public void test2() { List<? extends Person> list1 = null; List<? super Person> list2 = null; List<Student> list3 = null; List<Person> list4 = null; List<Object> list5 = null; list1 = list3; list1 = list4; // list1 = list5;//编译不通过 // list2 = list3;//编译不通过 list2 = list4; list2 = list5; //读取数据 Person person = list1.get(0); // Student student = list1.get(0);//编译不通过 Object object = list2.get(0); // Person person1 = list2.get(0);//编译不通过 //写入数据: // list1.add(new Student());//编译不通过 // list1.add(new Person());//编译不通过 list2.add(new Person());//通过 list2.add(new Student());//通过 // list2.add(new Object());//编译不通过 }
    Processed: 0.016, SQL: 9