自定义泛型方法的练习与类型推断总结

    技术2025-03-26  11

    自定义泛型方法的练习与类型推断总结泛型方法的练习题·编写一个泛型方法,自动将Object类型的对象转换成其他类型。@SuppressWarnings("unchecked")private static <T> T autoConvertType(Object obj){ return (T)obj;}main方法中核心代码Object obj = "abc";//String str1 = obj; //Type mismatch: cannot convert from Object to String str1 =autoConvertType(obj);System.out.println(obj);·定义一个方法,可以将任意类型的数组中的所有元素填充为相应类型的某个对象。·采用自定义泛型方法的方式打印出任意参数化类型的集合中的所有内容。 -在这种情况下,前面的通配符方案要比泛型方法更有效,当一个类型变量用来表达两个参数之间或者参数和返回值之间的关系时, 即同一个类型变量在方法签名的两处被使用,或者类型变量在方法体代码中也被使用而不是仅在签名的时候使用,才需要使用泛型方法。代码: public static void printCollection(Collection<Object> collection){  collection.add("String");  for(Object obj: collection){   System.out.println(obj);  }  //collection  = new HashSet<Date>();//会报告错误 } public static void printCollection1(Collection<?> collection){  //clos.add("String");//错误,因为它不知自己未来匹配就一定是String  for(Object obj: collection){   System.out.println(obj);  }  collection.size();//没错,此方法与类型参数没有关系

      collection  = new HashSet<Date>();//Collection<?> a可以与任意参数化的类型匹配 } public static <T> void printCollection2(Collection<T> collection){  //collection.add("String");//The method add(T) in the type Collection<T> is not applicable for the arguments (String)  for(Object obj: collection){   System.out.println(obj);  }  collection.size();//没错,此方法与类型参数没有关系

      collection  = new HashSet<T>();//Collection<T> a必须与T类型的参数化的类型匹配 } 

    ·定义一个方法,把任意参数类型的一个数组中的数据安全地复制到相应的类型的集合中。·定义一个方法,把任意参数类型的一个数组中的数据安全地复制到相应类型的另一个数组中。示意代码: private static <T> void copy1(Collection<T> dest,T[] src){} private static <T> void copy2(T[] dest,T[] src){} copy1(new Vector<String>(),new String [10]); //copy1(new Vector<Date>(),new String [10]);/*copy1中在定义Vector<Date>尖括号中的T指定为Date时,将传递给泛型方法中的泛型参数,此时泛型方法中的泛型参数T也是Date了,所有第二个参数数组指定为String[]的数组的时候编译器就报错了*/ copy2(new Date[10],new String[10]); //Date ∩ String = Object

    类型参数的类型推断·编译器判断泛型方法的实际类型参数的过程称为类型推断,类型推断是相对于知觉推断的,其实现方法是一种非常复制的过程。·根据调用泛型方法时实际传递参数类型或返回值的类型来推断,具体规则如下: -当某个类型变量值在整个参数列表中的所有参数和返回值中的一处被应用类,那么根据调用方法时该处的实际应用类型来确定,这很容易凭着感觉推断出来,即直接根据调用方法时传递的参数类型或返回值来决定泛型参数的类型,例如: swap(new String[3],3,4) --> static <E> void swap(E[] a,int i,int j) -当某个类型变量在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法时这多处的实际应用类型都对应同一种类型来确定,,这很容易凭着感觉推断出来,例如: add(2,5) -->static <T> T add (T a, T b) -当某个类型变量在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法时这多处的实际应用类型对应到类不同的类型,且没有使用返回值,这时候取多个参数中的最大交集类型,例如,下面语句实际对应的类型就是Number了,编译没问题,只是运行时出问题: fill(new Integer[3],3.5f)-->static <T> void fill(T[], T v)//Integer∩Float = Number ,它们都是Number的子类 -当某个类型变量在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法时这多处的实际应用类型对应到了不同的类型,并且使用返回值,这时候优先考虑返回值的类型,例如,下面语句实际对应的类型就是Integer了,编译将报告错误,将变量x的类型改为float,对比eclipse报告的错误提示,接着再将变量x类型改为Number,则没有了错误: int x = add(3,3.5f) -->static <T> T add(T a,T b)

    定义泛型的类型·如果类的实例对象中的多处都要用到同一个泛型参数,即这些地方引用的泛型类型要保持同一个实际类型时,这时候就要采用泛型类型的方式进行定义,也就是类级别的泛型,语法格式如下: public class GeneriDao<T>{  private T field1;  public void save(T obj){}  public T getById(int id){} }·类级别的泛型时根据引用该类名时指定的类型信息来参数化类型变量的,例如,如下两种方式都可以: -GenericDao<String> dao = null; -new GenericDao<String>();·注意: -在对泛型类型进行参数化时,类型参数的实例必须是引用类型,不能是基本类型。 -当一个变量被声明为泛型时,只能被实例变量和方法调用(还有内嵌类型),而不能被静态变量和静态方法调用。因为静态成员是 被所有参数化的类所共享的,所以静态成员不应该有类级别的类型参数。·问题:类中只有多个方法需要使用泛型,是使用类级别的泛型,还是使用方法级别的泛型?  答:使用类级别的。示例代码:package lqq.heima.day2;

    import java.util.Set;

    //dao --data access object -->crudpublic class GenericDao <T>{ public  void  add(T x){} public T findById(int i){  return null; } public void delete(T obj){} public void delete(int i){} public void update(T obj){} public T findByUserName(String name){  return null; } public Set<T>  findByConditions(String where) {  return null; }  //静态方法使用泛型的时候不可以使用类级别的泛型参数,只能定义该方法自己的泛型参数类型,注意此处的T与类上的T是不同的。 public static <T> void staticMethod(T obj){} 

    }

    最新回复(0)