标签:
------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
(一). 泛型
1.1 介绍
泛型是JDK5.0新增加的一个特性,泛型的本质是参数化类型,即所操作的数据类型都被指定为一个参数。这种类型参数可以用在类、接口、和方法的创建中,分别称为泛型类、泛型接口、泛型方法。Java语言引入泛型的好处是安全简单。
1.2 认识泛型
在JDK5.0之前,没有泛型的情况下,通过对类型Object的引用来实现参数的"任意化",但"任意化"带来的缺点是需要显示的强制类型转换,此种转换要求开发者对实际参数类型预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不会提示错误,但在运行的时候会出现异常,这是一个安全隐患。
1.3 泛型的优势
使用泛型的优势在于编译期间检查类型,捕捉类型不匹配错误,并且所有的转换都是自动和隐式多的,提高代码复用率。
(二). 泛型的使用
2.1 泛型定义
实例化泛型类的语法结构如下:
1 classname<type-param-list> obj = new classname<type-param-list> (cons-arg-list);
泛型定义通常使用一个唯一的大写字母表示一个类型参数。
2.2 代码演示
1 //创建泛型类 2 public class Generic <T> { 3 private T ob;//定义泛型成员变量 4 public Generic(T ob){ 5 this.ob = ob; 6 } 7 public T getOb(){ 8 return ob; 9 } 10 public void setOb(T ob){ 11 this.ob = ob; 12 } 13 public void showType(){ 14 System.out.println("实际类型是:" + ob.getClass().getName()); 15 } 16 }
接下来创建类:
1 //创建测试类,用于解释泛型的使用方法 2 public class GenericDemo { 3 public static void main(String[] args) { 4 //定义泛型类Genneric的一个Integer版本 5 Generic<Integer> intOb = new Generic<Integer>(88); 6 intOb.showType(); 7 int i = intOb.getOb(); 8 System.out.println("value=" + i); 9 System.out.println("---------------------------------"); 10 //定义泛型类Genneric的一个String版本 11 Generic<String> strOb = new Generic<String>("Hello"); 12 strOb.showType(); 13 String s = strOb.getOb(); 14 System.out.println("value=" + s); 15 } 16 }
运行结果:
1 实际类型是:java.lang.Integer 2 value=88 3 --------------------------------- 4 实际类型是:java.lang.String 5 value=Hello
2.3 理解泛型需注意3点
(三). 有界类型
3.1 介绍
在有些时候需要对类型参数的取值进行一定程度的限制,以使数据具有可操作性。为了处理这种情况,Java提供了有界类型。在指定类型参数时可以使用extends关键字限制此类型参数代表的类必须继承自指定父类或父类本身。比如创建一个类:public class BoundGeneric<T extends Number>{},BoundGeneric类的定义中,使用extends关键字将T的类型限制为Number类及其子类。
3.2 注意
在使用extends(如:T extends someClass)声明的泛型类进行实例化时,运行传递的类型参数是:如果someClass是类,可以传递someClass本身及其子类,如果someClass是接口,则可以传递实现接口的类。
3.3 通配符
通配符由”?“来表示,代表一个未知类型。
例如:public static void func(Generic <?> T){}或者结合有界类型使用
public static void func(Generic <? extends Number> T)
(四). 泛型的局限
4.1 泛型的局限性
其实Java并没有真正的实现泛型,是编译器在编译的时候在字节码上了做手脚(成为擦除),这种实现理念造成java泛型本身有很多漏洞,局限性很大。其中大多数限制性是由类型擦除引起的。
1 public class GenericException <T> extends Exception{ 2 //泛型类无法继承Throwable,非法 3 }
不能在catch子句中使用类型参数,如下面的方法将不能编译:
1 public static <T extends Throwable> void doWork(Class<T> t){ 2 try { 3 } catch (T e) {//不能捕获类型参数异常 4 } 5 }
但是,在异常声明中可以使用类型参数。下面这个是合法的:
1 public static <T extends Throwable> void doWork(T t) throws T { 2 try { 3 } catch (Throwable realCause) {//不能捕获类型参数异常 4 throw t; 5 } 6 }
1 public class Gen<T>{ 2 //静态变量不能引用类型参数 3 static T ob; 4 //静态方法不能引用类型参数 5 static T getOb(){ 6 return ob; 7 } 8 }
尽管不能在静态变量或静态方法中引用类型参数,但可以声明静态泛型方法。
(五). 技巧
当方法静态时,不能访问类上定义的泛型,如果静态方法使用泛型,只能将泛型定义在方法上,注意放置位置:public static <Y> void method(Y obj)
? extends E :接收E类型或者E的子类对象((对于本身来说是)上限)
? super E :接收E类型或者E的父类型(下限)
在集合存元素时,一般使用上限,因为这样取出都是按照上限类型来运算,不会出现安全隐患。
什么时候使用下限呢?
通常对集合中的元素进行取出操作时,可以用下限。
标签:
原文地址:http://www.cnblogs.com/pingfan21/p/4940668.html