1 好处:
泛型:
在编译时检查类型安全
所有的强制转换都是自动和隐式的,不需要手动强制转换类型。
2 应用地方:
2.1 泛型典型应用, 泛型声明类参数类型 、
/** * 泛型类:声明时使用泛型 * 字母: * T Type 表示类型。 K V 分别代表键值中的Key Value。 E 代表Element。 使用时确定类型 注意: 1、泛型只能使用引用类型,不能基本类型 2、泛型声明时字母不能使用 静态属性|静态方法上 * @author Administrator * * @param <T> */ public class Student<T1,T2> { private T1 javaScore; private T2 oracleScore; //泛型声明时不能使用 静态属性|静态方法上 //private static T1 test; public T1 getJavaScore() { return javaScore; } public void setJavaScore(T1 javaScore) { this.javaScore = javaScore; } public T2 getOracleScore() { return oracleScore; } public void setOracleScore(T2 oracleScore) { this.oracleScore = oracleScore; } /** * @param args */ public static void main(String[] args) { //使用时指定类型(引用类型) Student<String,Integer> stu = new Student<String,Integer> (); //1、安全:类型检查 stu.setJavaScore("优秀"); //2、省心:类型转换 int it =stu.getOracleScore(); //自动拆箱 不需要人工强制转换 } }
2.2 泛型声明接口参数类型
public interface Comparator<T> { void compare(T t); }
2.3 泛型用在方法形参中声明类型, 在真正调用方法传递真正参数时,才知道这个方法形参具体类型
public class TestMethod { /** * @param args */ public static void main(String[] args) { test("a"); //T -->String } //泛型方法 public static <T> void test(T a){ System.out.println(a); } // extends <= public static <T extends Closeable> void test(T... a){ for(T temp:a){ try { if(null!=temp){ temp.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
2.4 泛型在父子类的使用 :
package com.bjsxt.gen03; /** * 父类为泛型类, 泛型用在 * 1、属性 * 2、方法 * * 要么同时擦除,要么子类大于等于父类的类型, * 不能子类擦除,父类泛型 * 1、属性类型, 属性随位置而定 在哪里定义的就跟着哪块类型 * 属性定义在父类中,随父类而定 * 属性定义在子类中,随子类而定, 如果同名属性出现在了父类和子类中并且使用不同的泛型,那么子类使用中这个属性跟随子类泛型类型 * 2、方法重写时: * 方法中形参的泛型随父类而定 * * * @author Administrator * * @param <T> */ public abstract class Father<T,T1> { T name; public abstract void test(T t); } /** * 子类声明时指定具体类型 * 属性类型为具体类型 * 方法同理 */ class Child1 extends Father<String,Integer>{ String t2; @Override public void test(String t) { // 方法中形参的泛型随父类而定,父类中定义方法test(T t)在子类继承时,明确指定第一个形参为String,那么这个重写的方法的参数就是String this.name = ""; // name属性是定义在父类中的 } } /** * 子类为泛型类 ,类型在使用时确定,子类的泛型可以扩展 * @author Administrator * */ class Child2<T1,T,T3> extends Father<T,T1>{ T1 t2; T1 name; // 同名属性出现在父类和子类中,那么name跟随子类泛型走 @Override public void test(T t) { } } /** * 子类为泛型类,父类不指定泛型类型时,父类的泛型的擦除(失效),父类中原来定义的泛型r<T,T1>会使用Object替换掉 */ class Child3<T1,T2> extends Father{ T1 name2; @Override public void test(Object t) {//父类的方法跟随父类的泛型 这里父类泛型给擦除掉 因此形参就是Object 不会跟随子类走 // TODO Auto-generated method stub Object object = this.name; // 可以使用eclipse查看 this.name返回的类型是Object } } /** * 子类与父类同时擦除, 就是子类和父类都不使用泛型了 */ class Child4 extends Father{ String name; @Override public void test(Object t) { } } /** *错误:子类擦除,父类使用泛型 class Child5 extends Father<T,T1>{ String name; @Override public void test(T t) { } */
2.5 泛型 ?的使用
/** * 通配符 * ?类型不定,使用时确定类型 * ?使用:声明类型|声明方法上,不能声明类或使用时 * ? extends : <= 上限 指定类型 子类或自身 * ? super :>=下限 指定类型 为自身或父类 * @author Administrator * */ public class Student<T> { T score; public static void main(String[] args) { Student<?> stu = new Student<String>(); // =左侧是声明泛型, =右侧是使用时,在使用时不能使用? test(new Student<Integer>()); // test2(new Student<Apple>()); //test3(new Student<Apple>()); //泛型没有多态 , 打开注释时会编译报错, //test4(new Student<Apple>()); //< 编译不通过 stu = new Student<Fruit>();; //test4(stu); //使用时确定类型 编译不通过 test4(new Student<Object>()); test4(new Student<Fruit>()); } public static void test(Student<?> stu){ } public static void test3(Student<Fruit> stu){ } // <= public static void test2(Student<? extends Fruit> stu){ } //>= public static void test4(Student<? super Fruit> stu){ } }
2.6 没有泛型数组
/** * 没有泛型数组 * 声明可以使用,但是创建失败 * @author Administrator * */ public class Array { /** * @param args */ public static void main(String[] args) { Integer[] arr = new Integer[4]; //Student<String>[] arr2 = new Student<String>[10]; Student<?>[] arr2 = new Student[10]; MyArrayList<String> strList =new MyArrayList<String>(); strList.add(0, "a"); String elem =strList.getElem(0); System.out.println(elem); } } class MyArrayList<E>{ //E[] cap =new E[10]; 没有泛型数组, = 左侧可以声明,但是 =右侧如果使用时 编译失败,因此 没有泛型数组 Object[] cap = new Object[10]; public void add(int idx,E e){ cap[idx] =e; } @SuppressWarnings("unchecked") public E[] getAll(){ return (E[]) cap; } @SuppressWarnings("unchecked") public E getElem(int idx){ // 没有泛型数组 在获取时强制进行类型转换 并添加注解 压制警告 return (E) cap[idx]; } }
2.7 jdk1.7中对泛型的改进 :
/** * 1.7中使用泛型,声明一次类型即可 * 在使用|创建时不用指定类型 * @author Administrator * */ public class Test7 { /** * @param args */ public static void main(String[] args) { List<String> arrList= new ArrayList<String>(); // jdk1.6和以下版本下定义方式 List<String> arrList2= new ArrayList<>(); // jdk1.7时, 只需要声明一次即可 } }