Java泛型及实践
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Java泛型及实践,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含6173字,纯文字阅读大概需要9分钟。
内容图文
代码及说明:
1 package com.zsm.crazyjava; 2 3 import java.util.ArrayList; 4 import java.util.Collection; 5 import java.util.List; 6 import java.util.Set; 7 8 /** 9 * @author zsm 10 * @date 2016年11月2日 下午11:23:30 11 * @version 1.0 12 * @parameter 13 * @return 14 */ 15 // JDK5开始支持泛型。泛型(类、接口、方法);泛型通配符、通配符上限、通配符下限 16 public class _16_Generic { 17 // 泛型 18 List<String> strListStand = new ArrayList<String>(); 19// 泛型菱形语法(JDK7后初始化时泛型的具体类型可省略,自动判断) 20 List<String> strList = new ArrayList<>(); 21 22// 泛型类、接口 23publicinterface Fruit<T> { 24void add(T fruit); 25 } 26 27publicinterface MyMap<K, V> { 28 Set<K> keySet(); 29 30 V put(K key, V value); 31 } 32 33publicstaticclass Apple<T> { 34private T info; 35 36public Apple() {// 不能再写成Apple<T> 37 38 } 39 40public Apple(T info) { 41this.info = info; 42 } 43 44public T getInfo() { 45returnthis.info; 46 } 47 48// 静态方法、静态初始化块、静态变量声明和初始化中不能使用泛型形参,静态类或接口定义处则可以 49// static T name;//报错 50// public static void bar(T msg) {} 51// static {T name = "xiaoming";} 52 53// 泛型方法则可以使用类型形参,即使是静态方法。类型形参放在方法修饰符和返回值之间 54publicstatic <E, F> void ttt(E name, F age) { 55 ; 56 } 57 } 58 59// 泛型派生的子类、实现泛型接口的类的声明中不能再包含泛型形参 60publicclass A1 extends Apple<String> {// 不能再写成Apple<T> 61public String getInfo() { 62returnsuper.info; 63 } 64 } 65 66// 带泛型形参的类不会随着类型实参的不同而成为不同的类,接口亦然 67staticvoid testClassEqual() { 68 System.out.println((new Apple<String>()).getClass() == (new Apple<Integer>()).getClass());// true 69 List<String> strList = new ArrayList<>(); 70 List<Integer> intList = new ArrayList<>(); 71 System.out.println(strList.getClass() == intList.getClass());// true 72 } 73 74// 若Foo是Bar的子类,则Foo[]是Bar[]的子类,但List<Foo>却不是List<Bar>的子类。可以使用泛型通配符:?, 75publicvoid wildcardTest1(List<Object> c) {// 调用时只能传入List<Object>参数,不可传入List<String>等参数,因为后者不是前者的子类 76for (int i = 0; i < c.size(); i++) { 77 System.out.println(c.get(i)); 78 } 79 } 80 81publicvoid wildcardTest2(List<?> c) {// 此时可传入List<String>等参数,但只可从c读不可往里写,因为c类型不定。即带类型通配符定义的对象只可读不可写 82for (int i = 0; i < c.size(); i++) { 83 System.out.println(c.get(i)); 84// c.add(new Object());//编译错误,不可往c里写,因为c里元素类型未定 85 } 86 } 87 88// 类型通配符上限 89publicabstractclass Shape { 90publicabstractvoid draw(MyCanvas c); 91 } 92 93publicclass Circle extends Shape { 94 @Override 95publicvoid draw(MyCanvas c) { 96// TODO Auto-generated method stub 97 System.out.println("draw a circle on " + c); 98 } 99 } 100101publicclass Rectangle extends Shape { 102 @Override 103publicvoid draw(MyCanvas c) { 104// TODO Auto-generated method stub105 System.out.println("draw a rectangle on " + c); 106 } 107 } 108109publicclass MyCanvas { 110publicvoid drawAll0(List<?> shapes) {// 使用通配符时类型未定,所以访问每个元素只能用终极父类Object,这导致得进行麻烦的强制类型转换111for (Object obj : shapes) { 112 Shape s = (Shape) obj; 113 s.draw(this); 114 } 115 } 116117publicvoid drawAll1(List<? extends Shape> shapes) {// 使用通配符上限,从而知道元素元素类型的终极父类是Shape,这样不用进行强转。至多可以有一个类上限、多个接口上限,类上限需放最前。118for (Shape s : shapes) { 119 s.draw(this); 120 } 121 } 122 } 123124// 泛型方法:方法中所用类型形参不要求在类声明中先出现该类型形参;类型形参位于方法修饰符和返回值之间;与泛型类、接口不同的是,无须在调用泛型方法时显式指明实参类型125public <T> void fromArrayToCollection(T[] a, Collection<T> c) {// a的实参可以是T[]的子类型126for (T o : a) { 127 c.add(o); 128 } 129 } 130131publicvoid test_fromArrayToCollection() { 132 fromArrayToCollection((new Object[10]), new ArrayList<Object>()); 133 fromArrayToCollection((new Integer[10]), new ArrayList<Object>()); 134 fromArrayToCollection((new Integer[10]), new ArrayList<>());// 与泛型类、接口不同的是,无须在调用泛型方法前显式指明实参类型(指在方法名前),编译器自己确定135 fromArrayToCollection((new Integer[10]), new ArrayList<Number>()); 136// fromArrayToCollection((new Integer[10]), new ArrayList<String>());//编译错误137 } 138139// 泛型方法和类型通配符:方法参数间或返回值与参数间存在类型依赖关系(如子类)时采用泛型方法,否则类型参数只用一次,没有存在的必要,可以改用类型通配符。140public <T, S extends T> void copy1(List<T> des, List<S> src) {// S仅用了一次且与其他参数间没有依赖关系,因此没有存在的必要,改为下面的方法。141for (S s : src) { 142 des.add(s); 143 } 144 } 145146public <T> void copy2(List<T> des, List<? extends T> src) {// 去掉S,改为使用类型通配符上限。147for (T t : src) { 148 des.add(t); 149 } 150 } 151152// 泛型方法 ———— 泛型构造器153class Foo<E> { 154public <T> Foo(T t) { 155 System.out.println(t); 156 } 157158publicvoid add(E e) { 159160 } 161 } 162163publicvoid test_genericConstructor() { 164new Foo("good"); 165new Foo(1); 166new<String> Foo("good");// 显示指定构造方法类型形参的实际类型167new<String> Foo<Integer>("good");// 又指定了类的类型形参的实际类型168new Foo<>("good");// 菱形语法 169// new<String> Foo<>(1);// 如果显示指定了构造器类型形参的类型,则不可用菱形语法170171 Foo<Integer> p1 = new<String> Foo("good"); 172 Foo<Integer> p2 = new<String> Foo<Integer>("good"); 173 Foo<Integer> p3 = new Foo<Integer>("good"); 174// Foo<Integer> p4 = new<String> Foo<>("good");//如果显示指定了构造器类型形参的类型,则不可用菱形语法175 } 176177// 类型通配符下限。 178// 返回最后一个元素,类型不可丢。上面的copy2方法如果要返回最后一个被复制的元素,则返回的会是des中元素的类型T,这样就丢失了src的类型即S。可以通过修改copy1解决,也可以通过通配符下限解决。179public <T, S extends T> S copy3(List<T> des, List<S> src) {// S仅用了一次且与其他参数间没有依赖关系,因此没有存在的必要,改为下面的方法。180int i = 0; 181for (i = 0; i < src.size(); i++) { 182 des.add(src.get(i)); 183 } 184return src.get(i - 1); 185 } 186187public <T> T copy4(List<? super T> des, List<T> src) {// 去掉S,改为类型通配符下限。188int i = 0; 189for (i = 0; i < src.size(); i++) { 190 des.add(src.get(i)); 191 } 192return src.get(i - 1); 193 } 194195// 檫除与转换:带泛型声明的类间转换196publicstaticvoid test_Transform() { 197 List list;// 不指定实际类型参数,为raw type,默认为上限类型,此为Object198 List<Integer> listInteger = new ArrayList<Integer>(); 199 listInteger.add(1); 200 listInteger.add(2); 201 list = listInteger;// List<Integer>对象赋给未指定类型的List,原始类型丢失,变为Object202203 List<String> listStr = list;// 编译没问题,只有警告:"未经检查的转换"204 System.out.println(listStr.get(0));// 但访问里面元素,会发生运行时异常205 } 206207publicstaticvoid main(String[] args) { 208// TODO Auto-generated method stub209210 } 211212 }
原文:http://www.cnblogs.com/z-sm/p/6259859.html
内容总结
以上是互联网集市为您收集整理的Java泛型及实践全部内容,希望文章能够帮你解决Java泛型及实践所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。