泛型(Generics)是由编译器来验证从客户端将一种类型传送给某一对象的机制,实现了数据类型的参数化.
1.在使用泛型之前,先来看一下没有泛型的java集合框架(Collection)
import java.util.ArrayList; import java.util.List; public class GenericsDemo1 { private final List list = new ArrayList(); public void addList() { list.add("test"); list.add(10); } public void showList() { for (Object o : list) { System.out.println(((String) o)); } } public static void main(String[] args) { GenericsDemo g = new GenericsDemo(); g.addList(); g.showList(); } }
此段程序中包含两个方法,addList方法为list中增加了一个String类型和一个int类型;showList方法中,由于Collection在内部用的是Object,我们需要用String进行强制转换,运行时会出现ClassCastException.
在实际开发中,开发这必须用实际类型进行Cast,编译器无法检查,代码在运行时会有抛出ClassCastException的危险.
2.使用泛型
j2se在1.5为所有的Collection都加入了泛型的声明,例如:
public class ArrayList<E> extends AbstractList<E> { public void add(E element) { } public Iterator<E> iterator() { } }
这里的E是一个类型变量,并没有对它进行具体类型的定义,只是一个类型占位符,由使用者指定类型.通过使用泛型可增加类型安全:
>>在类型没有变化时,Collection是类型安全的;
>>类型的匹配错误在编译期间就可以捕捉到;
>>内在的类型转换优于在外部的人工造型;
>>使接口更加强壮,因为它增加了类型;
使用泛型修改第1节中的程序:
import java.util.ArrayList; import java.util.List; public class GenericsDemo2 { private final List<String> list = new ArrayList<String>(); public void addList() { list.add("test"); // list.add(10); } public void showList() { for (String o : list) { System.out.println(o); } } public static void main(String[] args) { GenericsDemo g = new GenericsDemo(); g.addList(); g.showList(); } }
注意,使用泛型后,list.add(10)类型匹配错误,无法通过编译.
3.类型通配符
通过泛型可以做到限制类型,那么能否利用'多态'的特性呢?
List<Object> list = new ArrayList<String>();
如上,定义了一个存储Object类型的List,利用'多态'的特性,创建了一个String类型的ArrayList赋给list.
实际上,这行代码是无法正常编译的,应该使用以下定义方式:
List<?> list3 = new ArrayList<String>();
其中?表示unknown类型,能与其他类型进行匹配,类似于'父类',称作类型通配符.有以下表现形式:
<E> >> E类型
<? extends E> >> 继承E的unknown类型
<? super E> >> E的unknown父类型
<?> >> unknown类型
下面通过一个例子来了解这几种通配符:
import java.util.ArrayList; import java.util.List; public class GenericsDemo3 { public void a() { List<Object> list = new ArrayList<>(); list.add(new Object()); list.add("a"); list.add(97); list.add(null); } public void b() { List<? extends Object> list = new ArrayList<String>(); // list.add(new Object()); // list.add("b"); // list.add(98); list.add(null); } public void c() { List<? super String> list = new ArrayList<>(); // list.add(new Object()); list.add("c"); // list.add(99); list.add(null); } public void d() { List<?> list = new ArrayList<>(); // list.add(new Object()); // list.add("d"); // list.add(100); list.add(null); } }
此段程序包含的四个方法中,
在a方法中,泛型类型确定为Object,可成功添加四个元素;
在b方法中,list的定义是没问题的,但list.add("b")却无法通过编译,可知list内存储的数据类型的编译类型是unknown的,因此无法添加一个String.
在c方法中,定义了一个存储String的父类的list,但list.add(new Object())却无法通过编译,而list.addd("c")却能执行通过,由此可见此时<? super String>与<String>作用相同.
在d方法中,由于?是unknown类型,所以Object,String,Integer都是无法被添加的.
由于null是所有类的对象,所以上述四个方法中的list.add(null)都是可以成功执行的.
4.自定义泛型<T>
在编程过程中,通过<T>表示一个类型,具体类型由使用者提供,如:Map<K,V>{},推荐的命名:
K >> key,map的键
V >> value,list和set的内容,map的值
E >> 异常类
T >> 泛型
例:
public class GenericsDemo4 { public static <T extends Comparable<T>> T max(T t1, T t2) { if (t1.compareTo(t2) > 0) { return t1; } return t2; } public static void main(String[] args) { System.out.println(max(98, 97)); System.out.println(max("a", "b")); // System.out.println(max(97, "b")); } }
此段程序在max方法中定义了一个泛型T,T实现了Comparable接口(不能用implements,只能用extends),Comparable比较的类型又是T,同时也将T作为参数和返回值.
在main方法中调用了3次max,只有前两次能够编译并执行,在第三次调用max(97,"b")时,传入的参数分别是Integer和String,编译器无法判断返回值的类型,无法完成编译.
执行后输出结果:
98
b
另外注意,定义的<T>可以同时继承类和实现接口,用&连接,上述的max方法也可如下定义:
public static <T extends Object & Comparable<T>> T max(T t1, T t2) { if (t1.compareTo(t2) > 0) { return t1; } return t2; }
5.小结
泛型(Generics),实现类数据类型的参数化,通过使用泛型,对数据类型自动检查,避免了类型转换,增加了程序的安全性.
相关推荐
Java 实现泛型List的源码,基本实现了List接口的全部所有方法。欢迎大家发表自己的观点和建议。
java 泛型方法使用示例 java 泛型方法使用示例 java 泛型方法使用示例
Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战Java中的泛型简析实战...
2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip2.java定义泛型类.zip...
Java Generics and Collections 英文版,详细描述java 泛型技术
主要介绍了Java中泛型使用实例详解的相关资料,需要的朋友可以参考下
java 使用泛型,优化重复多余代码.
Java泛型编程指南.pdf 此文章译自SUN的泛型编程指南
java 继承泛型类示例 java 继承泛型类示例 java 继承泛型类示例
这是一个使用JAVA实现的泛型编程,分为两部分,第一部分创建泛型类,并实例化泛型对象,得出相加结果。 第二部分用户自行输入0--4,选择要进行的加减乘除运算或退出,再输入要进行运算的两个数,并返回运算结果及...
主要给大家介绍了关于Java中泛型使用的简单方法,文中通过示例代码介绍的非常详细,对大家学习或者使用Java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
Java1.5泛型指南中文版
Java泛型使用详细分析.pdf
java 泛型类的类型识别示例 java 泛型类的类型识别示例 java 泛型类的类型识别示例
java5泛型新特性 pdf,自己看不解释!
java 一个关于泛型的简单例子 java 一个关于泛型的简单例子 java 一个关于泛型的简单例子
深入理解java泛型,包括类名泛型的定义,方法泛型定义,泛型的返回
在Java中运用反射+泛型,实现数据库的动态增删改查等功能,可以是Mysql, 也可以是SQL Server,oracle 也行。本代码是支持SQL Server和oracle的。
Java中的泛型结构请大家指教并指导有不足的地方给予赐教。