Java--泛型

xiaoxiao2021-02-28  42

Java集合的缺点:

把对象“丢进”集合后,集合就会”忘记“这个对象的数据类型,取出时编译类型变成object类型,运行时类型没变。

这样做的原因:设计它的程序员不知用他存放何种类型对象,就设计成object类型,具有通用性。

这样带来了两个问题:

1、集合对元素类型没有任何限制,如只想创建保存单一类型集合,但程序丢进其它类型,引发异常。

2、取出元素时进行强制类型转换既增加编程复杂度,又可能引发ClassCastException异常。

泛型的好处:一是类型安全;二是消除强制类型转换。

定义泛型:

public class fru<T> {

    private T info;     public fru() {}          public fru(T info)     {     this.info =info;     }     public void setInfo(T info)     {     this.info=info;     }     public T getInfo()     {     return this.info;

    }

派生子类:

可以从带泛型声明的接口、父类来派生子类。

public class A extends fru<T>{}   --错误

public class A extends fru<String>{}   --使用方法时必须为所有的数据形参传入参数值。

也可以不传入实际类型--public class A extends fru{} ,但会发出泛型检查警告,系统将类fru<T>中的T形参当成object类型来处理。

public class A2 extends fru{

   public String  getInfo()

    {

        //super.getInfo()方法返回值是object类型,所以加toString()才返回String类型。

     return super.getInfo().toString();

    }

并不存在泛型类:

泛型对其所以可能的类型参数,具有同样的行为,可以把相同的类当成许多不同的类来处理。Java类的静态方法、静态初始化或者静态变量的声明和初始化中,不允许使用类型参数。因为系统中不会真正生成泛型类,instanceof运算符处理后不能使用泛型类。

类型通配符:

     数组和泛型有所不同,如果SubClass是SuperClass的子类或者子接口,则SubClass[]依然是SuperClass[]的子类,但G<SubClass>不是G<SuperClass>的子类。

      类型通配符,写作List<?>,表示各种泛型List的父类,它的元素类型可以匹配任何类型,?称作通配符。

   List<?>c=new ArrayList<String>();

       c.add(new Object());    //引发编译错误

带通配符的List仅表示各种泛型的父类,并不能把元素加入其中,因为并不知程序中C集合中的元素类型。但有一例外,c.add(null);null是所有引用类型的实例。

设置类型通配符上限:

import java.util.*;

public class Canvas { //同时在画布上绘制多个形状 public void drawAll(List<? extends Shapes>) { for(Shape s : shapes)     {          s.draw(this);      } } public static void main(String[] args) { List<Circle> circleList=new ArrayList<Circle>(); circleList.add(new circle()); Canvas c=new Canvas(); c.drawAll(circleList);

}

设置类型形参上限:

import java.util.*;public class ffruu<T extends Numbers>{ T cool; public static void main(String[] args) { ffruu<integer> ai=new ffruu<integer>(); ffruu<Double> ad=new ffruu<Double>(); ffruu<String> as=new ffruu<String>(); //引起编译异常,String类型传给T形参,但String不是Number的子类型 }

}

另一种情况是,程序需要为类型形参设定多个上限(至多一个父类上限,可以有多个接口上限),表明该类型形参必须是其父类的子类(父类本身也行),并且实现多个上限接口。

public class Apple<T extends Numbers & java.io.Serializable>{...} 

上面程序表明T类型必须是Number类或其子类,并必须实现 java.io.Serializable接口。

声明泛型方法:

import java.util.*;public class cefang { //声明一个泛型方法,该泛型方法中带一个T形参 static<T>void fromArrayToCollection(T[]a,Collection<T> c) { for(T o : a) c.add(o); } public static void main(String[] args) { Object[] oa=new Object[100]; Collection<Object>co=new ArrayList<Object>(); //下面代码中T代表Object类型 fromArrayToCollection(oa,co); String[] sa = new String[100]; Collection<String>cs=new ArrayList<String>(); //下面代码中T代表String类型 fromArrayToCollection(sa,cs); //下面代码中T代表Object类型 fromArrayToCollection(sa,co); Integer[] ia =new Integer[100]; Float[] fa=new Float[100]; Number[] na =new Number[100]; Collection<Number>cn=new ArrayList<Number>(); //下面代码中T代表Number类型 fromArrayToCollection(ia,cn); //下面代码中T代表Number类型 fromArrayToCollection(fa,cn); //下面代码中T代表String类型 fromArrayToCollection(na,co); //下面代码中T代表String类型,但na是一个Number数组 //因为Number既不是String类型,也不是它的子类,所以出现编译错误 //fromArrayToCollection(na,cs); }

}

设置通配符下限:

public static void fun(Info<? super String>temp){   //只能接收String或者Object类型的泛型

     System.out.println(temp);

}

通过泛型方法返回泛型类:

class Info<T extends Number>{}  //指定上限,只能是数字类型

public class genneric{

    public static <T extends Number>Info<T>fun(T temp){

          Info<T>info=new Info<T>();

          Info.setVar(temp);

          return info;   //返回实例化对象

     }

}

  

转载请注明原文地址: https://www.6miu.com/read-2619654.html

最新回复(0)