泛型

来源:互联网 发布:深圳中学学位房 知乎 编辑:程序博客网 时间:2024/06/05 08:37

泛型——JdK1.5以后出现的技术 ——安全机制!

泛型的由来:

集合中可以存储任意类型的对象,但是在取出时,如果要使用具体对象的特有方法时,需要进行向下转型,如果存储的对象类型不一致,在转型过程中就会出现ClassCastException异常,这样就给程序带来了不安全性。然而,这种不安全性会发生在运行时期,用户无法解决。

【代码体现:】

import java.util.ArrayList;import java.util.Iterator;public class GenericDemo {public static void main(String[] args) {ArrayList a1 = new ArrayList();a1.add("abc1");a1.add("hahah");a1.add(6); //a1.add(Integer.valueOf(6));Iterator it = a1.iterator();while(it.hasNext()){String s = (String)it.next();System.out.println(s.length());}}}
运行时会出现如下提示:

Exception in thread "main"  java.lang.ClassCastException:   java.lang.Integer cannot be cast to java.lang.String
at .  GenericDemo.main(GenericDemo.java:19)

如何解决呢?

在JdK1.5以后就有了解决方案,就是泛型技术。

解决方案就是:

在存储元素时,就不允许存储不同类型的元素。存储了就编译失败。所以就需要在存储元素时,在容器上明确具体的元素类型。这其实和数组定义很像。

【代码体现】

import java.util.ArrayList;import java.util.HashSet;import java.util.Iterator;public class GenericDemo {public static void main(String[] args) {//定义了一个ArrayList集合,并明确该集合中只能存储String类型的元素。ArrayList<String> al = new ArrayList<String>();al.add("abc1");al.add("hahah");//al.add(6);//al.add(Integer.valueOf(6)); 在编译时期就报错Iterator<String> it = al.iterator();while(it.hasNext()){String s = it.next();System.out.println(s.toString());}}}

【泛型的好处】

1. 将运行时期的ClassCastException异常转移到了编译时期,进行检查,并以编译失败来提示,这样有利于程序员尽早解决问题。

2. 避免了向下转型的麻烦。


【什么时候写泛型呢?】

只要在使用类或接口时,该类或者接口在api文档描述时都带着<>就需要在使用时,定义泛型。其实,泛型无非就是通过< >定义了一个 形式参数。专门用于接收具体的引用类型。在使用时,一定要传递对应的实际参数类型。

【泛型的擦除:】

       泛型技术是用于编译时期的技术,编译器会按照<>中的指定类型对元素进行检查, 检查不匹配,就编译失败,匹配,就编译通过,通过后,生成的class文件中时没有泛型的。这就是:泛型的擦除。

      

【泛型的补偿:】

       运行时,可以根据具体的元素对象获取其类型(既然已经编译通过,那么就已经保证了对象类型的一致性)。并用该类型对元素进行自动转换。

————————————————————————————————————————————————————————————————————— 

【泛型类】

当一个类要操作的引用数据类型不确定的时候,可以将该类型定义一个形参。用到的这类时,由使用者来通过传递类型参数的形式,来确定要操作的具体

的对象类型。 意味着在定义这个类时,需要在类上定义形参。用于接收具体的类型实参。这就是将泛型定义在类上。这就是泛型类。

【什么时候使用泛型类呢?】

只要类中操作的引用数据类型不确定的时候,就可以定义泛型类。有了泛型类,省去了曾经的强转和类型转换异常的麻烦。

 【代码体现】

class Worker{private String name;private int age;public void work(){}}class student{private String name;private int age;public void study(){}}class Util<duixiang>{private duixiang obj;public void setObject(duixiang obj){this.obj = obj;}public duixiang getObject(){return obj;}}public class GenericDemo1 {public static void main(String[] args) {Util<Worker> u = new Util<Worker>();u.setObject(new Worker());Worker w = u.getObject();Util<student> u1 = new Util<student>();u1.setObject(new student());student w1 = u1.getObject();}}

【方法泛型】


要操作的类型不确定的,但是不一定和调用该方法的对象指定的类型一致。可以将泛型定义在方法上。

 

静态方法不能访问类上定义的泛型,如果需要泛型,该泛型只能定义在方法上。

【代码体现】

public class GenericDemo3 {public static void main(String[] args) {Tool2<String> t = new Tool2<String>();t.show("abc");t.myprint("haha");t.myprint(new Integer(4));t.method("nihao");}}class Tool2<W>{public void show(W w){System.out.println("show:"+w.toString());}/* * 这个myprint方法,要操作的类型不确定的,但是不一定和调用该方法的对象指定的类型一致。 * 可以将泛型定义在方法上。  */public <A> void myprint(A a){System.out.println("myprint:"+a.toString());}/* * 静态方法不能访问类上定义的泛型,如果需要泛型,该泛型只能定义在方法上。 */public   static <Y> void method(Y w){System.out.println("method:"+w);}}

【泛型接口】

public class GenericDemo4 {public static void main(String[] args) {/* * 泛型接口。 */new InterImpl().show("abc");new InterImpl2<Integer>().show(new Integer(5));}}interface Inter<V>{public abstract void show(V v);}//实现接口时,也不明确具体类型。 class InterImpl2<C> implements Inter<C>{public void show(C c){System.out.println("show :"+c);}}//实现接口时,明确具体的类型。 class InterImpl implements Inter<String>{public void show(String s){System.out.println("show :"+s);}}

【泛型的高级应用】

【泛型的通配符:】

当操作的不同容器中的类型都不确定的时候,而且使用的都是元素从Object类中继承的方法。这时泛型就用通配符?来表示即可。

【代码体现】

import java.util.ArrayList;import java.util.Collection;import java.util.Iterator;public class GenericAdvDemo {/** * @param args */public static void main(String[] args) {ArrayList<String> a1 = new ArrayList<String>();a1.add("abc1");a1.add("abc2");a1.add("abc3");ArrayList<Integer> a2 = new ArrayList<Integer>();a2.add(5);a2.add(9);a2.add(1);printColl(a1);printColl(a2);}/** * 创建一个用于迭代集合的功能 * @param b */private static void printColl(Collection<?> b) {Iterator<?> it = b.iterator();while(it.hasNext()){System.out.println(it.next().toString());}}}

【泛型的限定】

能不能对操作的类型限制在一个范围之内呢?

比如:定义一个功能,只操作Person类型或者Person的子类型。 这时可以用 ? extends E:接收E类型或者E的子类型。这就是上限。

 下限:? super E: 接收E类型或者E的父类型。GenericAdvDemo2

【什么时候使用上限呢?】一般情况下,只要是往容器中添加元素时,使用上限。  ? extends E

【什么时候使用下限呢?】一般清况下,只要是从容器中取出元素时,是用下限。 ? super E

【代码体现】

import java.util.ArrayList;import java.util.Collection;import java.util.Iterator;public class GenericAdvDemo2 {/** * @param args */public static void main(String[] args) {ArrayList<Person> al = new ArrayList<Person>();al.add(new Person("lisi1",21));al.add(new Person("lisi2",22));al.add(new Person("lisi3",23));print(al);ArrayList<Student> al2 = new ArrayList<Student>();al2.add(new Student("xiaoming1",21));al2.add(new Student("xiaoming2",22));al2.add(new Student("xiaoming3",23));print(al2);ArrayList<Worker> al3 = new ArrayList<Worker>();al3.add(new Worker("xiaohong1",21));al3.add(new Worker("xiaohong2",22));al3.add(new Worker("xiaohong3",23));print(al3);}public static void print(Collection<? extends Person> coll){Iterator<? extends Person> it = coll.iterator();while(it.hasNext()){System.out.println(it.next().getName());}}}public class Person implements Comparable {private String name;private int age;public Person() {super();}public Person(String name, int age) {super();this.name = name;this.age = age;}/** * @return the name */public String getName() {return name;}/** * @param name the name to set */public void setName(String name) {this.name = name;}/** * @return the age */public int getAge() {return age;}/** * @param age the age to set */public void setAge(int age) {this.age = age;}/* (non-Javadoc) * @see java.lang.Object#toString() */@Overridepublic String toString() { return name+":"+age;}/** * 按照Person的年龄进行比较。这是Person的自然顺序。 */@Overridepublic int compareTo(Object o) {Person p = (Person)o;int temp = this.age - p.age;return temp==0?this.name.compareTo(p.name):temp;}}public class Student extends Person {public Student() {super();}public Student(String name, int age) {super(name, age);}}public class Worker extends Person {public Worker() {super();}public Worker(String name, int age) {super(name, age);}}



	
				
		
原创粉丝点击