黑马程序员学习笔记之五(java中的泛型)

来源:互联网 发布:js 计算时间差 编辑:程序博客网 时间:2024/05/20 16:37

---------------------- android培训、java培训、期待与您交流! ----------------------


 

泛型的概念

泛型(Generic type 或者 generics)是对java语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类。可以把类型参数看作是使用参数化类型时指定的类型的一个占位符,就像方法的形式参数是运行时传递的值的占位符一样。

可以在集合框架(Collection framework)中看到泛型的动机。例如,Map 类允许您向一个 Map 添加任意类的对象,即使最常见的情况是在给定映射(map)中保存某个特定类型(比如 String)的对象。

因为 Map.get() 被定义为返回 Object,所以一般必须将 Map.get() 的结果强制类型转换为期望的类型,如下面的代码所示:

Map m = new HashMap();
m.put("key", "blarg");
String s = (String) m.get("key");

要让程序通过编译,必须将 get() 的结果强制类型转换为 String,并且希望结果真的是一个 String。但是有可能某人已经在该映射中保存了不是 String 的东西,这样的话,上面的代码将会抛出 ClassCastException。

理想情况下,您可能会得出这样一个观点,即 m 是一个 Map,它将 String 键映射到 String 值。这可以让您消除代码中的强制类型转换,同时获得一个附加的类型检查层,该检查层可以防止有人将错误类型的键或值保存在集合中。这就是泛型所做的工作。

 

 泛型的好处

Java语言中引入泛型是一个较大的功能增强。不仅语言、类型系统和编译器有了较大的变化,以支持泛型,而且类库也进行了大翻修,所以许多重要的类,比如集合框架,都已经成为泛型化的了。这带来了很多好处:

类型安全。泛型的主要目标是提高Java程序的类型安全。通过知道使用泛型定义的变量的类型限制,编译器可以在一个高得多的程度上验证类型假设。没有泛型,这些假设就只存在于程序员的头脑中(或者如果幸运的话,还存在于代码注释中)。

示例:

import java.util.*;class GenericDemo2 {public static void main(String[] args) {TreeSet<String> ts = new TreeSet<String>(new LenComparator());ts.add("abcd");ts.add("cc");ts.add("cba");ts.add("aaa");ts.add("z");ts.add("hahaha");Iterator<String> it = ts.iterator();while(it.hasNext()){String s = it.next();System.out.println(s);}}}class LenComparator implements Comparator<String>{public int compare(String o1,String o2){int num = new Integer(o2.length()).compareTo(new Integer(o1.length()));if(num==0)return o2.compareTo(o1);return num;}}

 

 

泛型类

泛型类最常见的用例是容器类(比如集合框架)。编写一个类,用来接收或者返回一个Worker或者Student类型的对象,我们采用两种方式来实现,一种不使用泛型,一种使用泛型,进行对比。

/*class Tool{private Worker w;public void setWorker(Worker w){this.w = w;}public Worker getWorker(){return w;}}*/class Worker{}class Student{}//泛型前做法。class Tool{private Object obj;public void setObject(Object obj){this.obj = obj;}public Object getObject(){return obj;}}//泛型类。/*什么时候定义泛型类?当类中要操作的引用数据类型不确定的时候,早期定义Object来完成扩展。现在定义泛型来完成扩展。*/class Utils<T>{private T t;public void setObject(T t)
{this.t = t;}public T getObject(){return t;}}class  GenericDemo3{public static void main(String[] args) {Utils<Worker> u = new Utils<Worker>();u.setObject(new Student());Worker w = u.getObject();;/*Tool t = new Tool();t.setObject(new Student());Worker w = (Worker)t.getObject();*/}}

 

泛型方法

通过在类的定义中添加一个形式类型参数列表,可以将类泛型化。方法也可以被泛型化,不管它们定义在其中的类是不是泛型化的。

泛型类在多个方法签名间实施类型约束。在 List<V> 中,类型参数 V 出现在 get()、add()、contains() 等方法的签名中。当创建一个 Map<K, V> 类型的变量时,您就在方法之间宣称一个类型约束。您传递给 add() 的值将与 get() 返回的值的类型相同。

类似地,之所以声明泛型方法,一般是因为您想要在该方法的多个参数之间宣称一个类型约束。如下:

 

//泛型类定义的泛型,在整个类中有效。如果被方法使用,//那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。////为了让不同方法可以操作不同类型,而且类型还不确定。//那么可以将泛型定义在方法上。/*特殊之处:静态方法不可以访问类上定义的泛型。如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上。*/class Demo<T>{public  void show(T t){System.out.println("show:"+t);}public <Q> void print(Q q){System.out.println("print:"+q);}public  static <W> void method(W t){System.out.println("method:"+t);}}class GenericDemo4 {public static void main(String[] args) {Demo <String> d = new Demo<String>();d.show("haha");//d.show(4); // show方法接受的参数类型已经声明为String类型了,不能接受Integerd.print(5);d.print("hehe");Demo.method("hahahahha");/*Demo d = new Demo();d.show("haha");d.show(new Integer(4));d.print("heihei");*//*Demo<Integer> d = new Demo<Integer>();d.show(new Integer(4));d.print("hah");Demo<String> d1 = new Demo<String>();d1.print("haha");d1.show(5);*/}}

特殊之处:
静态方法不可以访问类上定义的泛型。
如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上。

 

泛型接口

泛型定义在接口上面,通常在数据库的CRUD操作中比较常见,代码如下:

// 泛型定义在接口上interface Dao<T>{void save(T t);    T find(id);void delet(T t);void update(T t);}class JDBCDao<T> implements Dao<T> // 使用JDBC实现CRUD操作{public void save(T t){// ...}public T find(T t){// ...}public void find(T t){// ...}public void update(T t){// ...}}class HibernateDao implements Dao<T> // 使用Hibernate实现CRUD操作{public void save(T t){// ...}public T find(T t){// ...}public void find(T t){// ...}public void update(T t){// ...}}class GenericDemo5 {public static void main(String[] args) {Student s = new Student();// 使用JDBC进行CRUD操作Dao dao<Student> = new JDBCDao<Student>();dao.add(s)// 使用JDBC进行CRUD操作Dao dao<Student> = new HibernateDao<Student>();dao.delete(s);}}


 

泛型通配符与泛型限定

 

在前面的泛型的例子中,类型参数 T是无约束的或无限制的 类型。有时在还没有完全指定类型参数时,需要对类型参数指定附加的约束。

 

import java.util.*;/*? 通配符。也可以理解为占位符。泛型的限定;? extends E: 可以接收E类型或者E的子类型。上限。? super E: 可以接收E类型或者E的父类型。下限*/class  GenericDemo6{public static void main(String[] args) {/*ArrayList<String> al = new ArrayList<String>();al.add("abc1");al.add("abc2");al.add("abc3");ArrayList<Integer> al1 = new ArrayList<Integer>();al1.add(4);al1.add(7);al1.add(1);printColl(al);  // 此处调用的是 printColl(ArrayList<?> al)方法,ArrayList中可以存放任何类型的对象printColl(al1);*/ArrayList<Person> al = new ArrayList<Person>();al.add(new Person("abc1"));al.add(new Person("abc2"));al.add(new Person("abc3"));//printColl(al);ArrayList<Student> al1 = new ArrayList<Student>();al1.add(new Student("abc--1"));al1.add(new Student("abc--2"));al1.add(new Student("abc--3"));printColl(al1);  //ArrayList<? extends Person> al = new ArrayList<Student>();error}public static void printColl(Collection<? extends Person> al) // Collection 中可以是Person类及其子类对象{Iterator<? extends Person> it = al.iterator();while(it.hasNext()){System.out.println(it.next().getName());}}/*// ? 通配符,表示泛型中的参数可以是任何类型public static void printColl(ArrayList<?> al)//ArrayList al = new ArrayList<Integer>();error{Iterator<?> it = al.iterator();while(it.hasNext()){System.out.println(it.next().toString());}}*/}// class Person{private String name;Person(String name){this.name = name;}public String getName(){return name;}}class Student extends Person{Student(String name){super(name);}}class Comp implements Comparator<Person> //<? super E>{public int compare(Person s1,Person s2){//Person s1 = new Student("abc1");return s1.getName().compareTo(s2.getName());}}class  GenericDemo7{public static void main(String[] args) {TreeSet<Student> ts = new TreeSet<Student>(new Comp());ts.add(new Student("abc1"));ts.add(new Student("abc2"));ts.add(new Student("abc3"));}}


上例中的Comp比较器既可以接受Person对象,也可以接受Student对象。

 

---------------------- android培训、java培训、期待与您交流! ----------------------

原创粉丝点击