java泛型

来源:互联网 发布:淘宝店卖什么最赚钱 编辑:程序博客网 时间:2024/06/05 14:56

泛型定义:

              Class tuple<A,B>{

                     Public final       A first;//泛型A的实例变量first;

                     Public final  B second;//泛型B的实例变量second;    

                     Public tuple(A a,B b){first= a; second = B;}//构造函数初始化AB泛型。

              }

       泛型继承:

              Classtuple2<A,B,C> extends tuple<A,B>{

                     Public final C third;//泛型C的定义;

                     Public tuple2(A a,B b,C c){super(a,b);      //继承上层的泛型

                            Third = c;                 //构造函数初始化泛型C

                     }

       泛型使用:

              定义函数使用泛型作为返回值:

                     Tuple<String ,Integer>  function(){

                            Return  new Tuple<String, Integer>(“hi”,  47);//返回值新建了一个泛型tuple并且指定了其泛型类型为String和Integer,然后分别初始化了String与Integer为hi和47;

                     }

 

泛型方法:

       Public <T>  void f(T x){

}//此处<T>置于void前的方法即为泛型方法,方法中可以使用泛型参数。

       使用泛型类,必须在创建类时指明其类型,当时泛型函数可以自己判断出传入的泛型参数是什么。

可变参数:

       可变参数其实就是 “…”,这在C语言中也存在。例如W… args;表示泛型W的args参数可选,可以有多个

泛型擦出:

       Java的泛型是用擦出来实现的,这意味着你在使用泛型时,任何具体的类型信息都被擦除了,你唯一知道的就是你在使用一个对象。因此List<String>和List<Integer>在运行时其实是相同类型。这两种形式都被擦除为其原生的List类型,理解擦除以及如何处理时泛型的最大难点。

解决方案例:

class HasF{

                   publicvoid f(){ System.out.println("HasF.f()");}

}

classManipulator<T>{

         privateT obj;

         publicManipulator(TxT) {

                   //TODOAuto-generated constructor stub

                   obj= xT;

         }       

         publicvoid manipulate() {

                   obj.f();//因为擦除了类型信息,编译器此处不知道obj中是否包含f()这个函数,故报错

         }

}

classManipulator2<T extends HasF>{

         privateT obj;

         publicManipulator2( Tx) {

                   //TODOAuto-generated constructor stub

                   obj= x;

         }

         publicvoid manipulate(){

                   obj.f();//这里协助泛型建立了边界,编译器知道其实继承自HasF,故而调用成功。

         }

}

此处泛型类将擦除到他的第一边界,实际中他可能有多个边界。

擦除的代价是显著地,泛型不能用于显示的运行时类型的操作之中,例如转型,instanceof操作和new表达式

@SuppressWarnings("unchecked")压制警告要聚焦,不能放在整个类上,那样和压制真正的警告

 

擦除的补偿:

class Building{}

class House extends Building{}

classClassTypeCapture<T> {

         Class<T> kind;

         T obj;

         publicClassTypeCapture(Class<T>kind) throws InstantiationException,IllegalAccessException {

                   //TODOAuto-generated constructor stub

                   this.kind =kind;

                   obj= kind.newInstance();  /*这句创建了泛型实例,实际编译器是根据传入的类型参数用         newInstance()函数创建的泛型实例

                                     此外,这个操作需要抛出异常*/

         }

         publicboolean f(Objectarg) {

                   returnkind.isInstance(arg);//instanceof不能用,可以用isInstance来检验标签出入类型参数后是否可以在类型表达式中使用

         }       

}

public class Tag {

         publicstaticvoidmain(String[] args) throws InstantiationException,IllegalAccessException {

                   //TODOAuto-generated method stub

                            ClassTypeCapture<Building>ctt1 =

                                               new ClassTypeCapture<Building>(Building.class);

                            System.out.println(ctt1.f(new Building()));

                            System.out.println(ctt1.f(new House()));

                            ClassTypeCapture<House>ctt2 =

                                               new ClassTypeCapture<House>(House.class);

                            System.out.println(ctt2.f(new Building()));

                            System.out.println(ctt2.f(new House()));       

         }

}

 

注意:

List<? ExtendsFruit> flist = new ArrayList<Apple>();//这句意味着一旦执行list的类型转为< ? Extends  Fruit>,他讲不能接受接受添加是不能接受对父类不同类型的添加

List<? SuperApple> list = new ArrayList<>();这样可以接受添加工作。

 

泛型的问题:

1.    任何基本类型不能作为类型参数如:ArrayList<int>是错误的,但ArrayList<Integer>没有问题

2.    不能实现参数化接口:interfacepayable<T> {}

Class Employeeimplements payable<Employee>{}

Class Hourlyextends Employee implements Payable<Hourly>{}

这样是编译通不过的,由于擦除导致子类父类实现同一个接口。了

3.    使用带泛型参数的转型和instanceof不会有任何效果

4.    重载不能编译:public classUseList<W,T>{

a)      Void f(List<T> v ) {}

b)     Void f(List<W> v ) {}实际上由于编译器擦除,编译器看到的是void f(List v){}这一个函数,故这种情况下函数不能重名

0 0
原创粉丝点击