输出结果: interface List< T > 和 class GenTest<K,V> 结论:子类必须是“富二代”,子类除了指定或保留父类的泛型,还可以增加自 方法,也可以被泛型化,不管此时定义在其中的类是不是泛型类。在泛型方法中可以定义泛型参数,此时,参数的类型就是传入数据的类型。 泛型方法的格式: 虽然类A是类B的父类,但是G< A > 和G< B >二者不具备子父类关系,二者是并列关系。 因为我们不知道c的元素类型,我们不能向其中添加对象。add方法有类型参数E作为集合的元素类型。我们传给add的任何参数都必须是一个未知类型的子类。因为我们不知道那是什么类型,所以我们无法传任何东西进去。 //注意点1:编译错误:不能用在泛型方法声明上,返回值类型前面<>不能使用? 举例:目录
1. 泛型的用处
@Test public void test1() { ArrayList<String> list = new ArrayList<>(); list.add("hello"); list.add(" world"); //list.add(12); //错误 //此时类型已经明确为String for (String s : list) { System.out.print(s); } }
从上面的小例子就可以看出,在集合中使用泛型,只有指定的类型才能添加到集合中,类型安全,读取出来的对象也不需要强转,便携。保证如果程序在编译时没有发出警告,运行时就不会产生ClassCastException异常。 同时,代码更加简洁、健壮。2. 泛型类与接口
2.1 基本用法
2.1.1 泛型的声明
其中,T,K,V不代表值,而是表示类型。这里使用任意字母都可以。常用T表示,是Type的缩写。2.1.2 示例
public class Order <T>{ private T OrderT; public T getOrderT() { return OrderT; } public void setOrderT(T orderT) { OrderT = orderT; } } ********************************************* public static void main(String[] args) { //创建对象并指定类型 Order<String> order = new Order<>(); order.setOrderT("张三"); String s = order.getOrderT(); System.out.println(s);//张三 //创建对象并指定类型 Order<Integer> order1 = new Order<>(); order1.setOrderT(123); //order1.setOrderT("123"); 类型不一致 编译错误 Integer t = order1.getOrderT(); System.out.println(t);//123 }
2.2 注意事项
public GenericClass(){}。
而下面是错误的:public GenericClass<E>(){}
ArrayList<String>
和ArrayList<Integer>
是两种类型,但是,在运行时只有一个ArrayList被加载到JVM中。也就是说,无论何时定义一个泛型类型,都自动提供一个相应的原始类型。 原始类型的名字就是删去类型参数后的泛型类型名。擦除类型变量,并替换为限定类型(无限定类型的变量用Object)
中不能使用类的泛型。E[] elements = (E[])new Object[capacity];
己的泛型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> { } class Father<T1, T2> { } // 子类不保留父类的泛型 // 1)没有类型 擦除 class Son<A, B> extends Father{//等价于class Son extends Father<Object,Object>{ } // 2)具体类型 class Son2<A, B> extends Father<Integer, String> { } // 子类保留父类的泛型 // 1)全部保留 class Son3<T1, T2, A, B> extends Father<T1, T2> { } // 2)部分保留 class Son4<T2, A, B> extends Father<Integer, T2> { }
3. 泛型方法
[访问权限] <泛型> 返回类型 方法名([泛型标识 参数名称]) 抛出的异常public <E> E get( E e){}
public static <T> void fromArrayToCollection(T[] a, Collection<T> c) { for (T o : a) { c.add(o); } } public static void main(String[] args) { Object[] ao = new Object[100]; Collection<Object> co = new ArrayList<Object>(); fromArrayToCollection(ao, co); String[] sa = new String[20]; Collection<String> cs = new ArrayList<>(); fromArrayToCollection(sa, cs); Collection<Double> cd = new ArrayList<>(); // 下面代码中T是Double类,但sa是String类型,编译错误。 // fromArrayToCollection(sa, cd); // 下面代码中T是Object类型,sa是String类型,可以赋值成功。 fromArrayToCollection(sa, co); }
4. 泛型类型的继承规则
补充:类A是类B的父类,A< G > 是 B< G > 的父类
比如:String是Object的子类,但是List< String >并不是List< Object >的子类 @Test public void test1(){ Object obj = null; String str = null; obj = str; Object[] arr1 = null; String[] arr2 = null; arr1 = arr2; //编译不通过 // Date date = new Date(); // str = date; List<Object> list1 = null; List<String> list2 = new ArrayList<String>(); //此时的list1和list2的类型不具子父类关系 //编译不通过 // list1 = list2; /* 反证法: 假设list1 = list2; list1.add(123);导致混入非String的数据。出错。 */ show(list1); show1(list2); } public void show1(List<String> list){ } public void show(List<Object> list){ } @Test public void test2(){ AbstractList<String> list1 = null; List<String> list2 = null; ArrayList<String> list3 = null; list1 = list3; list2 = list3; List<String> list4 = new ArrayList<>(); }
5. 通配符类型
5.1 没有限制的通配符
如:Collection<?> c = new ArrayList<String>(); c.add(new Object()); // 编译时错误
@Test public void test3(){ List<Object> list1 = null; List<String> list2 = null; List<?> list = null; list = list1; list = list2; //编译通过 // print(list1); // print(list2); // 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); //获取(读取):允许读取数据,读取的数据类型为Object。 Object o = list.get(0); System.out.println(o); } public void print(List<?> list){ Iterator<?> iterator = list.iterator(); while(iterator.hasNext()){ Object obj = iterator.next(); System.out.println(obj); } }
public static <?> void test(ArrayList<?> list){
}
//注意点2:编译错误:不能用在泛型类的声明上
class GenericTypeClass<?>{
}
//注意点3:编译错误:不能用在创建对象上,右边属于创建集合对象
ArrayList<?> list2 = new ArrayList<?>();5.2有限制的通配符
上限extends:使用时指定的类型必须是继承某个类,或者实现某个接口,即<=
下限super:使用时指定的类型不能小于操作的类,即>=
<? extends Number> (无穷小 , Number] 只允许泛型为Number及Number子类的引用调用
<? super Number> [Number , 无穷大) 只允许泛型为Number及Number父类的引用调用 @Test public void test4(){ 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; //读取数据: list1 = list3; Person p = list1.get(0); //编译不通过,编译器只知道需要某个Person的子类型,但不知道具体是什么类型 //Student s = list1.get(0); list2 = list4; Object obj = list2.get(0); ////编译不通过,只能是Object类型 // Person obj = list2.get(0); //写入数据: //编译不通过 // list1.add(new Student()); //编译通过 list2.add(new Person()); list2.add(new Student()); }
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算