黑马程序员———java高级特性之泛型

来源:互联网 发布:安卓mac修改器apk 编辑:程序博客网 时间:2024/06/05 12:49

------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流------

一.泛型的内部原理

1.1泛型针对的是编译器,加载到内存中的字节码并没有泛型信息,示例代码如下:

public class GenericTest {public static void main(String[] args) {Collection<Integer> col1=new ArrayList<Integer>();Collection<String> col2=new ArrayList<String>();//泛型是针对编译器的,加载到内存中的字节码并没有泛型信息,所以输出trueSystem.out.println(col1.getClass()==col2.getClass());//通过反射可以跳过泛型限制,例如尝试向集合col1中添加字符串元素对象try {col1.getClass().getMethod("add", Object.class).invoke(col1, "abc");System.out.println(((ArrayList<Integer>) col1).get(0));//输出abc} catch (IllegalArgumentException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (SecurityException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InvocationTargetException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (NoSuchMethodException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}

1.2泛型中涉及到的一些概念

a.ArrayList<E>称为泛型类型,E称为类型变量或类型参数,ArrayList<Integer>称为参数化的类型,Integer称为实例类型参数,ArrayList称为原始类型,<>可以念做typeof。

b.参数化类型的引用变量可以指向一个原始类型的对象,例如:Collection<String> c=new Vector();但会报警告。

c.原始类型的引用变量也可以指向一个参数化类型的对象,例如:Collection c=new Vector<String>();也会报警告。

二.泛型的通配符扩展应用

2.1使用?通配符可以引用各种参数化的类型,但只能调用与参数化无关的方法,例如定义一个方法用于打印任意参数化类型的集合中的所有数据,示例代码如下:

public class GenericTest {public static void main(String[] args) {Collection<Integer> col1=new ArrayList<Integer>();Collection<String> col2=new ArrayList<String>();col1.add(1);col1.add(2);col1.add(3);col2.add("aaa");col2.add("bbb");col2.add("ccc");printCollection(col1);printCollection(col2);}public static void printCollection(Collection<?> col){for (Object object : col) {System.out.println(object);}}}

2.2通配符的上下边界

a.限定通配符的上边界:ArrayList<? extends Number> al=new ArrayList<Integer>();

b.限定通配符的下边界:ArrayList<?  super Integer> al=new ArrayList<Number>();

2.3泛型集合的综合应用,示例代码如下:

public class GenericTest {public static void main(String[] args) {HashMap<String, Integer> hm=new HashMap<String, Integer>();hm.put("zhangsan", 20);hm.put("lisi", 21);hm.put("wangwu", 22);Set<Map.Entry<String, Integer>> set=hm.entrySet();for (Entry<String, Integer> entry : set) {System.out.println(entry.getKey()+"="+entry.getValue());}}}

三.自定义泛型

3.1自定义泛型方法及其应用

a.定义一个泛型方法(泛型定义在返回值类型前面,紧挨返回值类型),交换任意引用类型数组中两个元素的位置,示例代码如下:

public class GenericTest {public static void main(String[] args) {String[] strs=new String[]{"aaa","bbb","ccc"};//注意只能传入引用类型的数组,不能传入基本类型数组swap(strs, 1, 2);for (String string : strs) {System.out.println(string);}}public static <T> void swap(T[] arr,int x,int y){T temp=arr[x];arr[x]=arr[y];arr[y]=temp;}}

b.定义一个泛型方法,将Object类型的对象转换为其他类型,示例代码如下:

public class GenericTest {public static void main(String[] args) {Object obj="abc";String str=autoConvert(obj);}public static <T> T autoConvert(Object obj){return (T)obj;}}

c.定义一个泛型方法,将任意类型数组中的数据复制到相应类型集合中,示例代码如下:

public class GenericTest {public static void main(String[] args) {Collection<String> dest=new ArrayList<String>();String[] src=new String[]{"aaa","bbb","ccc"};copy(dest, src);for (String string : dest) {System.out.println(string);}}public static <T> void copy(Collection<T> dest,T[] src){for (int i = 0; i < src.length; i++) {dest.add(src[i]);}}}
3.2自定义泛型类及其应用
a.当一个类要操作的引用数据类型不确定时,早期使用Object来扩展,现在使用泛型来进行扩展,泛型类与泛型方法最大的不同:定义泛型方法时,每个泛型方法中的泛型都是独立的;定义泛型类之后,每个方法(静态方法除外)使用的都是类上定义的泛型,属于同一个泛型。示例代码如下:

public class Student1 {private String name;private int age;public Student1(String name, int age) {super();this.name = name;this.age = age;}@Overridepublic String toString() {return "Student1 [age=" + age + ", name=" + name + "]";}}

public class Worker1 {private String name;private int age;public Worker1(String name, int age) {super();this.name = name;this.age = age;}@Overridepublic String toString() {return "Worker1 [age=" + age + ", name=" + name + "]";}}

public class Utils<T>{private T t;public void setObject(T t){this.t=t;}public T getObject(){return t;}public static void main(String[] args) {Utils<Student1> u1=new Utils<Student1>();u1.setObject(new Student1("zhangsan", 20));Student1 s=u1.getObject();System.out.println(s);Utils<Worker1> u2=new Utils<Worker1>();u2.setObject(new Worker1("lisi", 21));Worker1 w=u2.getObject();System.out.println(w);}}

b.泛型也可以定义在接口上,示例代码如下:

public interface Inter<T> {public void show(T t);}

class interImpl<T> implements Inter<T>{public void show(T t) {System.out.println(t);}public static void main(String[] args) {interImpl<Student1> inter=new interImpl<Student1>();inter.show(new Student1("wangwu", 22));}}


3.3通过反射获得一个方法中泛型类型的参数,示例代码如下:

public class GenericTest {public static void method(ArrayList<String> al){}public static void main(String[] args) {try {Method method=GenericTest.class.getMethod("method", ArrayList.class);Type[] types=method.getGenericParameterTypes();ParameterizedType pType=(ParameterizedType)types[0];System.out.println(pType.getRawType());//輸出class java.util.ArrayListSystem.out.println(pType.getActualTypeArguments()[0]);//輸出class java.lang.String} catch (SecurityException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (NoSuchMethodException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}




0 0