泛型的来源
在Java中,泛型借鉴了C++的模版函数,从而引入了泛型。
- C++泛型
int add(int x,int y){ return x + y; } float add(float x.float y){ return x + y; } double add(double x,double y){ return x + y; } // 泛型函数对上面的整数,浮点数的抽象和实现 template<class T> T add(T x,T y){ return x + y; }
- 自定义泛型
public class MyGeneric { public static void main(String[] args) { // 泛型推断的一般原则,用于返回泛型参数中的交集,且泛型参数必须为引用类型 // 3 自动装箱 Integer 5 自动装箱Integer 所以 推断出Integer Integer result1 = add(3, 5); // 3.5 自动装箱 Double 5 自动装箱Integer 所以推断出共有的父类Number Number result2 = add(3.5, 5); // 3 自动装箱Integer str1 String 共有的交集,都是Object Object result3 = add(3, "str1"); } /** * 泛型方法的定义: * 用于放置泛型的类型参数的尖括号应出现在方法的其他所有修饰符之后和在方法的返回类型之前,也就是紧邻返回值之前,下面的 <T> * 按照惯例,类型参数通常用单个大写字母表示 * 只有引用类型才会被当作方形方法的参数,会自动装箱的也算 * @param x * @param y * @return */ public static <T> T add(T x,T y) { // 这里编译器会报错:The operator + is undefined for the argument type(s) T, T // 因为不是所有的泛型都支持 + 操作,但是由这个方法可以看到java的类型推断 // T result = x + y; return null; } }
自定义泛型实战
- 编写一个泛型方法,自动将Object类型的对象转换成其他类型。
/** * 编写一个泛型方法,自动将Object类型的对象转换成其他类型。 * @param obj * @return */ private static <T> T autoConvert(Object obj) { return (T) obj; } // 测试代码 public static void main(String[] args) { Object object = "helloWorld"; String helloworld = autoConvert(object); System.out.println("helloworld = " + helloworld); }
- 定义一个方法,可以将任意类型的数组中的所有元素填充为相应类型的某个对象
/** * 定义一个方法,可以将任意类型的数组中的所有元素填充为相应类型的某个对象 * @param t 数组 * @param obj 对象 */ private static <T> void fillArray(T[] t,T obj) { for (int i = 0; i < t.length; i++) { t[i] = obj; } }
- 采用自定义泛型方法的方式打印出任意参数化类型的集合中的所有内容
/** * 采用自定义泛型方法的方式打印出任意参数化类型的集合中的所有内容 * @param t */ private static <T> void printArray(T[] t) { for (int i = 0; i < t.length; i++) { System.out.println("ele[" + i + "] = " + t[i]); } } /** * 采用自定义泛型方法的方式打印出任意参数化类型的集合中的所有内容 * @param t */ private static <T> void printArray(Collection<T> t) { int i = 0; for (T ele : t) { System.out.println("ele[" + (i++) + "] = " + ele); } }
- 定义一个方法,把任意参数类型的集合中的数据安全地复制到相应类型的数组中
/** * 定义一个方法,把任意参数类型的集合中的数据安全地复制到相应类型的数组中,体现了类型推断的传播性,T集合 与 T数组 的一致性 * @param source 源集合 * @param dest 目标数组 */ private static <T> void copy(Collection<T> source, T[] dest) { int i = 0; for (T ele : source) { dest[i++] = ele; } }
- 定义一个方法,把任意参数类型的一个数组中的数据安全地复制到相应类型的另一个数组中
/** * 定义一个方法,把任意参数类型的一个数组中的数据安全地复制到相应类型的另一个数组中 * @param source 源数组 * @param dest 目标数组 */ private static <T> void copy(T[] source, T[] dest) { int i = 0; for (T ele : source) { dest[i++] = ele; } }