[关闭]
@liayun 2016-06-01T18:08:33.000000Z 字数 5462 阅读 1664

泛型

java基础


泛型概述

泛型:JDK1.5版本以后出现的新特性。用于解决安全问题,是一个类型安全机制。

泛型格式

泛型格式:通过<>来定义要操作的引用数据类型

泛型的好处

泛型的好处:

  1. 将运行时期出现的问题ClassCastException,转移到了编译时期,方便于程序员解决问题,让运行时期问题减少,安全。
  2. 避免了强制转换的麻烦。

在使用java提供的对象时,什么时候写泛型呢?

问:在使用java提供的对象时,什么时候写泛型呢?
答:通常在集合框架中很常见,只要见到<>就要定义泛型。其实<>就是用来接收类型的。当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。
例,

  1. import java.util.*;
  2. class GenericDemo {
  3. public static void main(String[] args) {
  4. ArrayList<String> al = new ArrayList<String>();
  5. al.add("abc01");
  6. al.add("abc0991");
  7. al.add("abc014");
  8. // al.add(4);// al.add(new Integer(4));
  9. Iterator<String> it = al.iterator();
  10. while(it.hasNext()) {
  11. String s = it.next();
  12. System.out.println(s + ":" + s.length());
  13. }
  14. }
  15. }

练习:按照字符串长度排序。
解:

  1. import java.util.*;
  2. class GenericDemo2 {
  3. public static void main(String[] args) {
  4. TreeSet<String> ts = new TreeSet<String>(new LenComparator());
  5. ts.add("abcd");
  6. ts.add("cc");
  7. ts.add("cba");
  8. ts.add("aaa");
  9. ts.add("z");
  10. ts.add("hahaha");
  11. Iterator<String> it = ts.iterator();
  12. while(it.hasNext()) {
  13. String s = it.next();
  14. System.out.println(s);
  15. }
  16. }
  17. }
  18. class LenComparator implements Comparator<String> {
  19. public int compare(String o1, String o2) {
  20. int num = new Integer(o2.length()).compareTo(new Integer(o1.length()));
  21. if(num == 0)
  22. return o2.compareTo(o1);
  23. return num;
  24. }
  25. }

自定义泛型类

现在有两个类,分别为StudentWorker,如下:

  1. class Student {
  2. }
  1. class Worker {
  2. }

然后有一个工具类Tool要操作StudentWorker两个类,怎么办呢?
泛型前做法:

  1. class Tool {
  2. private Object obj;
  3. public void setObject(Object obj) {
  4. this.obj = obj;
  5. }
  6. public Object getObject() {
  7. return obj;
  8. }
  9. }

现在定义泛型来完成扩展:

  1. class Utils<QQ> {
  2. private QQ q;
  3. public void setObject(QQ q) {
  4. this.q = q;
  5. }
  6. public QQ getObject() {
  7. return q;
  8. }
  9. }

什么时候定义泛型类?
答:当类中要操作的引用数据类型不确定的时候,早期定义Object来完成扩展,现在定义泛型来完成扩展。

泛型方法

泛型类定义的泛型,在整个类中有效。如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了,为了让不同方法可以操作不同类型,而且类型还不确定,那么可以将泛型定义在方法上。
特殊之处:静态方法不可以访问类上定义的泛型。如果静态方法操作的引用数据类型不确定,可以将泛型定义在方法上。
例,

  1. class Demo<T> {
  2. public void show(T t) {
  3. System.out.println("show:"+t);
  4. }
  5. // 泛型方法
  6. public <Q> void print(Q q) {
  7. System.out.println("print:"+q);
  8. }
  9. // 静态泛型方法
  10. public static <W> void method(W t) {
  11. System.out.println("method:"+t);
  12. }
  13. }
  14. class GenericDemo4 {
  15. public static void main(String[] args) {
  16. Demo<String> d = new Demo<String>();
  17. d.show("haha");
  18. // d.show(4); // error
  19. d.print(5);
  20. d.print("hehe");
  21. Demo.method("hahahaha");
  22. }
  23. }

泛型接口

泛型可定义在接口上。如:

  1. interface Inter<T> {
  2. void show(T t);
  3. }

泛型接口的第一种实现方式:

  1. class InterImpl implements Inter<String> {
  2. public void show(String t) {
  3. System.out.println("show:"+t);
  4. }
  5. }

调用方式:

  1. InterImpl i = new InterImpl();
  2. i.show("haha");

泛型接口的第二种实现方式:

  1. class InterImpl<T> implements Inter<T> {
  2. public void show(T t) {
  3. System.out.println("show :"+t);
  4. }
  5. }

调用方式:

  1. InterImpl<Integer> i = new InterImpl<Integer>();
  2. i.show(4);

泛型的限定

?:通配符,也可以理解为占位符。
泛型的限定:

  1. ? extends E:可以接收E类型或者E类型的子类型,上限。
  2. ? super E:可以接收E类型或者E的父类型,下限。

泛型的上限

  1. class Person {
  2. private String name;
  3. Person(String name) {
  4. this.name = name;
  5. }
  6. public String getName() {
  7. return name;
  8. }
  9. }
  10. class Student extends Person {
  11. Student(String name) {
  12. super(name);
  13. }
  14. }
  15. class GenericDemo {
  16. public static void main(String[] args) {
  17. ArrayList<Person> al = new ArrayList<Person>();
  18. al.add(new Person("abc1"));
  19. al.add(new Person("abc2"));
  20. al.add(new Person("abc3"));
  21. printColl(al);
  22. ArrayList<Student> al1 = new ArrayList<Student>();
  23. al1.add(new Student("abc--1"));
  24. al1.add(new Student("abc--2"));
  25. al1.add(new Student("abc--3"));
  26. printColl(al1);
  27. }
  28. public static void printColl(ArrayList<? extends Person> al) {
  29. Iterator<? extends Person> it = al.iterator();
  30. while(it.hasNext()) {
  31. System.out.println(it.next().getName());
  32. }
  33. }
  34. }

当然了,只使用通配符?或泛型也是可以的,如下使用通配符?

  1. public static void printColl(ArrayList<?> al) {
  2. Iterator<?> it = al.iterator();
  3. while(it.hasNext()) {
  4. // toString()方法是Object类中方法,所以可使用,注意由于类型不确定,所以不可使用特有方法
  5. System.out.println(it.next().toString());
  6. }
  7. }

使用泛型,与使用通配符?还是有区别的,可以接收T类型并操作,如:

  1. public static void printColl(ArrayList<T> al) {
  2. Iterator<T> it = al.iterator();
  3. while(it.hasNext()) {
  4. T t = it.next();
  5. System.out.println(t.toString());
  6. }
  7. }

泛型的下限

根据TreeSet(Comparator<? super E> comparator)来讲解泛型的下限。
一个继承体系如下:

  1. class Person {
  2. private String name;
  3. Person(String name) {
  4. this.name = name;
  5. }
  6. public String getName() {
  7. return name;
  8. }
  9. public String toString() {
  10. return "person : "+name;
  11. }
  12. }
  13. class Student extends Person {
  14. Student(String name) {
  15. super(name);
  16. }
  17. }
  18. class Worker extends Person {
  19. Worker(String name) {
  20. super(name);
  21. }
  22. }

若将StudentWorker对象存入TreeSet集合,并按照姓名排序,则不用泛型的限定,须定义两个比较器,如下:

  1. class StuComp implements Comparator<Student> {
  2. public int compare(Student s1, Student s2) {
  3. return s1.getName().compareTo(s2.getName());
  4. }
  5. }
  6. class WorkerComp implements Comparator<Worker> {
  7. public int compare(Worker s1, Worker s2) {
  8. return s1.getName().compareTo(s2.getName());
  9. }
  10. }

调用代码:

  1. class GenericDemo {
  2. public static void main(String[] args) {
  3. TreeSet<Student> ts = new TreeSet<Student>(new StuComp());
  4. ts.add(new Student("abc03"));
  5. ts.add(new Student("abc02"));
  6. ts.add(new Student("abc06"));
  7. ts.add(new Student("abc01"));
  8. Iterator<Student> it = ts.iterator();
  9. while(it.hasNext()) {
  10. System.out.println(it.next().getName());
  11. }
  12. TreeSet<Worker> ts1 = new TreeSet<Worker>(new WorkerComp());
  13. ts1.add(new Worker("wabc--03"));
  14. ts1.add(new Worker("wabc--02"));
  15. ts1.add(new Worker("wabc--06"));
  16. ts1.add(new Worker("wabc--01"));
  17. Iterator<Worker> it1 = ts1.iterator();
  18. while(it1.hasNext()) {
  19. System.out.println(it1.next().getName());
  20. }
  21. }
  22. }

若使用泛型的下限,则只须定义一个比较器:

  1. class Comp implements Comparator<Person> {
  2. public int compare(Person p1, Person p2) {
  3. return p2.getName().compareTo(p1.getName());
  4. }
  5. }

调用代码:

  1. class GenericDemo {
  2. public static void main(String[] args) {
  3. TreeSet<Student> ts = new TreeSet<Student>(new Comp());
  4. ts.add(new Student("abc03"));
  5. ts.add(new Student("abc02"));
  6. ts.add(new Student("abc06"));
  7. ts.add(new Student("abc01"));
  8. Iterator<Student> it = ts.iterator();
  9. while(it.hasNext()) {
  10. System.out.println(it.next().getName());
  11. }
  12. TreeSet<Worker> ts1 = new TreeSet<Worker>(new Comp());
  13. ts1.add(new Worker("wabc--03"));
  14. ts1.add(new Worker("wabc--02"));
  15. ts1.add(new Worker("wabc--06"));
  16. ts1.add(new Worker("wabc--01"));
  17. Iterator<Worker> it1 = ts1.iterator();
  18. while(it1.hasNext()) {
  19. System.out.println(it1.next().getName());
  20. }
  21. }
  22. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注