泛型
一、 定义:
泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型 被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
二、 泛型的使用规则:
1) 泛型的基本参数只能是类类型,不能是简单数据类 型。
2) 同一种泛型可以对应不同的版本,不同版本的泛型类是不兼容的。
3) 泛型的参数类型可以有多个。
4) 泛型的参数类型可以用extends或supper以及通配符”?”
5) 泛型可以应用于类,接口,方法。
三、泛型的益处:
1) 避免了类型间的强制转换的风险。
2) 把运行时的异常转移到代码编译时期,降低程序在运行时的发生错误的风险。
四、定义泛型
1)泛型类
class GenericDemo<E>
{
E e;
public GenericDemo(E e) {
super();
this.e = e;
}
public E getE() {
return e;
}
public void setE(E e) {
this.e = e;
}
}
2)泛型接口
interface IGenericDemo<E>
{
public void medhod(E e1,E e2);
}
3)泛型方法
class GenericMethod
{
publicE> voidE
{
}
}
五、上限泛型
一种泛型定义为<? extends E>,其中E可以为不同的类型,限定为只能是类型本身或类型的子类型。如:
package cn.javastudy.p7.generic.demo;
import java.util.*;
public class Generic {
public static void main(String[] args)
{
//父类
Collection<GenericDemo<String>> cl=new ArrayList<GenericDemo<String>>();
//子类
Collection<GenericMethod<String>> c2=new ArrayList<GenericMethod<String>>();
//传父类
GenericTextDemo<GenericDemo<String>> gtd=new GenericTextDemo<GenericDemo<String>>(cl);
//传子类
GenericTextDemo<GenericDemo<String>> gtd1=new GenericTextDemo<GenericDemo<String>>(c2);
}
}
class GenericDemo<E>
{
E e;
public GenericDemo(E e) {
super();
this.e = e;
}
public E getE() {
return e;
}
public void setE(E e) {
this.e = e;
}
}
class GenericMethod<E> extends GenericDemo<E>
{
public GenericMethod(E e) {
super(e);
// TODO Auto-generated constructor stub
}
public <E> void method(E e)
{
}
}
class GenericTextDemo<E>
{
//泛型上限的核心代码
Collection<? extends E> gd=null;
publicCollection<? extends E> gd) {
super();
this.gd = gd;
}
}
六、泛型下限
一种泛型定义为<? super E>其中E是任务的类型,此限定为只能是E类型或E类型的父类型。如下:模拟一个TreeSet
package cn.javastudy.p6.generic.demo;
import java.util.*;
public class Generic {
public static void main(String[] args)
{
MyTreeSet<Person> p=new MyTreeSet<Person>(new GenericDemo<Person>(){
@Override
public int compar(Person e1, Person e2) {
int temp=e1.getName().compareTo(e2.getName());
return temp==0?e1.getOld()-e2.getOld():temp;
}});
p.add(new Person("a张三",30));
p.add(new Person("c李四",10));
p.add(new Person("f王五",80));
p.add(new Person("d赵六",25));
p.add(new Person("e刘七",60));
p.add(new Student("g小明同学",12));
p.add(new Student("h小张同学",15));
p.add(new Student("s小杨同学",8));
p.add(new Student("z小金同学",13));
Iterator<Person> ip=p.getIterator();
while(ip.hasNext())
{
Person p1=ip.next();
System.out.println(p1.getName()+" -"+p1.getOld());
}
}
}
interface GenericDemo<E>
{
public int compar(E e1,E e2);
}
class MyTreeSet<E>
{
LinkedList<E> t=new LinkedList<E>();
//泛型下限的核心代码
GenericDemo<? super E> comparator=null;
public MyTreeSet(GenericDemo<? super E> com)
{
this.comparator=com;
}
public void add(E e)
{
if(t.size()>0)
{
for(int i=0;i<t.size();i++)
{
int temp=comparator.compar(e, t.get(i));
if(temp<0)
{
t.add(i,e);
return;
}
}
t.add(e);
}
else
{
t.add(e);
}
}
@Override
public String toString() {
// TODO Auto-generated method stub
return t.toString();
}
public Iterator<E> getIterator()
{
return t.iterator();
}
}
class Person
{
String name=null;
int old=0;
public Person(String name, int old) {
super();
this.name = name;
this.old = old;
}
public String getName() {
return name;
}
public int getOld() {
return old;
}
}
class Student extends Person
{
public Student(String name, int old) {
super(name, old);
// TODO Auto-generated constructor stub
}
}
七、通配符“?”
泛型还可以用?为通配符,将代表所有类型,转什么类型都可以。如下:
class GenericDemo2
{
public void Method(List<?> c)
{
}
}
class GenericDemo2Test
{
public static void main(String[] args)
{
GenericDemo2 gd=new GenericDemo2();
Vector<Object> vt=new Vector<Object>();
ArrayList<String> al=new ArrayList<String>();
gd.Method(vt);
gd.Method(al);
}
}
八、使用泛型避免强转的例子。
package cn.javastudy.p7.genericofconvert.demo;
import java.util.*;
public class GenericOfConvert {
public static void main(String[] args)
{
GenericOfConvertDemo god=new GenericOfConvertDemo();
god.add(new GenericOfConvertDemo1(1));
god.add(new GenericOfConvertDemo1(2));
god.add(new GenericOfConvertDemo1(3));
god.add(new GenericOfConvertDemo1(4));
god.add(new GenericOfConvertDemo1(5));
god.add("abc");
Collection c=god.get();
Iterator it=c.iterator();
while(it.hasNext())
{
GenericOfConvertDemo1 god1=(GenericOfConvertDemo1)(it.next());
god1.myPrint();
}
}
}
class GenericOfConvertDemo
{
Collection ct=new ArrayList();
public void add(Object go1)
{
ct.add(go1);
}
public Collection get()
{
return ct;
}
}
class GenericOfConvertDemo1
{
int id;
public GenericOfConvertDemo1(int id) {
super();
this.id = id;
}
public void myPrint()
{
System.out.println("ID:"+this.id);
}
}
运行结果:
ID:1
ID:2
ID:3
ID:4
ID:5
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to cn.javastudy.p7.genericofconvert.demo.GenericOfConvertDemo1
at cn.javastudy.p7.genericofconvert.demo.GenericOfConvert.main(GenericOfConvert.java:17)
上面代码中没有加泛型新特性,需要强制转化,当对god.add("abc");成功添加,因为其添加条件为Object,意味着什么类型都可以传进,当在转化时,因为其无法转化为GenericOfConvertDemo1而发生运行时异常。
下在改为使用泛型之后:
package cn.javastudy.p7.genericofconvert.demo;
import java.util.*;
public class GenericOfConvert {
public static void main(String[] args)
{
GenericOfConvertDemo<GenericOfConvertDemo1> god=newGenericOfConvertDemo1>();
god.add(newGenericOfConvertDemo1(1));
god.add(newGenericOfConvertDemo1(2));
god.add(newGenericOfConvertDemo1(3));
god.add(newGenericOfConvertDemo1(4));
god.add(newGenericOfConvertDemo1(5));
//god.add("abc");
Collection<GenericOfConvertDemo1> c=god.get();
Iterator<GenericOfConvertDemo1> it=c.iterator();
while(it.hasNext())
{
GenericOfConvertDemo1
god1.myPrint();
}
}
}
class GenericOfConvertDemo<E>
{
Collection<E> ct=new ArrayList<E>();
public void add(E go1)
{
ct.add(go1);
}
public Collection<E> get()
{
return ct;
}
}
classGenericOfConvertDemo1
{
int id;
public GenericOfConvertDemo1(int id) {
super();
this.id = id;
}
public void myPrint()
{
System.out.println("ID:"+this.id);
}
}
运行结果:
ID:1
ID:2
ID:3
ID:4
ID:5
因为上面的代码中添加了泛型,所以不需要进行强转。当有//god.add("abc");编译时,就发生了错误。使用了泛型后,不需要强制转换了,把运行时的错误转到了编译时,减少了运行时错误。