Java常用对象API——泛型

ava常用对象API——泛型

 

泛型

jdk1.5出现的安全机制。

好处:
1,将运行时期的问题ClassCastException转到了编译时期。
2,避免了强制转换的麻烦。

<>:什么时候用?当操作的引用数据类型不确定的时候。就使用<>。将要操作的引用数据类型传入即可.
其实<>就是一个用于接收具体引用数据类型的参数范围。

在程序中,只要用到了带有<>的类或者接口,就要明确传入的具体引用数据类型 。

泛型技术是给编译器使用的技术,用于编译时期。确保了类型的安全。

import java.util.ArrayList;
import java.util.Iterator;public class GenericDemo {/*** @param args*/public static void main(String[] args) {int[] arr = new int[4];ArrayList<String> al = new ArrayList<String>();//泛型:明确传入的只能是String类型al.add("abc");//public boolean add(Object obj)al.add("hahah");
//		al.add(4);//al.add(new Integer(4));放不进去了Iterator<String> it = al.iterator();while(it.hasNext()){String str = it.next();System.out.println(str);}}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

运行时,会将泛型去掉,生成的class文件中是不带泛型的,这个称为泛型的擦除
为什么擦除呢?为了兼容运行的类加载器。

泛型的补偿:在运行时,通过获取元素的类型进行转换动作。使用者不必再强制转换了。

泛型在集合中的应用

例子:

import java.util.Iterator;
import java.util.TreeSet;import cn.itcast.p2.bean.Person;
import cn.itcast.p3.comparator.ComparatorByName;public class GenericDemo2 {/*** @param args*/public static void main(String[] args) {//泛型:传入Person类TreeSet<Person> ts = new TreeSet<Person>(new ComparatorByName());ts.add(new Person("lisi8",21));ts.add(new Person("lisi3",23));ts.add(new Person("lisi",21));ts.add(new Person("lis0",20));Iterator<Person> it = ts.iterator();while(it.hasNext()){Person p = it.next();System.out.println(p.getName()+":"+p.getAge());}}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
//ComparatorByName.java  这个比较器通过名称排序
import java.util.Comparator;import cn.itcast.p2.bean.Person;public class ComparatorByName implements Comparator<Person> {@Overridepublic int compare(Person o1, Person o2) {int temp = o1.getName().compareTo(o2.getName());return temp==0? o1.getAge()-o2.getAge(): temp;}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

运行结果:(对Person对象按名称排序)
在这里插入图片描述

泛型类

在jdk1.5后,使用泛型来接收类中要操作的引用数据类型。
泛型类。什么时候用?当类中的操作的引用数据类型不确定的时候,就使用泛型来表示。

public class Tool<QQ>{//泛型类private QQ q;public QQ getObject() {return q;}public void setObject(QQ object) {this.q = object;}
public class GenericDefineDemo3 {/*** @param args*/public static void main(String[] args) {Tool<Student> tool = new Tool<Student>();tool.setObject(new Worker());//在编译时就报错Student stu = tool.getObject();}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

泛型方法

public class Tool<QQ>{private QQ q;public QQ getObject() {return q;}public void setObject(QQ object) {this.q = object;}/*** 将泛型定义在方法上。* @param str*/public <W> void show(W str){System.out.println("show : "+str.toString());}public void print(QQ str){System.out.println("print : "+str);}/*** 当方法静态时,不能访问类中定义的泛型。* 如果静态方法使用泛型,只能将泛型定义在方法上。 泛型必须写在返回值类型的前面,静态修饰符的后面* @param obj*/public static <Y> void method(Y obj){System.out.println("method:"+obj);}
}public class GenericDefineDemo4 {/*** @param args*/public static void main(String[] args) {Tool<String> tool = new Tool<String>();tool.show(new Integer(4));tool.show("abc");tool.print("hahah");Tool.method("haha");//调用静态方法Tool.method(new Integer(9));}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

在这里插入图片描述

泛型接口

public class GenericDefineDemo5 {/*** @param args*/public static void main(String[] args) {InterImpl in = new InterImpl();in.show("abc");InterImpl2<Integer> in2 = new InterImpl2<Integer>();//实现子类对象的时候才知道具体的类型in2.show(5);}
}//泛型接口,将泛型定义在接口上。 
interface Inter<T>{public void show(T t);
}class InterImpl2<Q> implements Inter<Q>{ //实现接口的时候继续定义泛型public void show(Q q){System.out.println("show :"+q);}
}class InterImpl implements Inter<String>{//实现接口,明确参数类型public void show(String str){System.out.println("show :"+str);}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

泛型限定

泛型的通配符:? 用来代表未知类型。

演示1:?通配符

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;public class GenericAdvanceDemo {/*** @param args*/public static void main(String[] args) {ArrayList<String> al = new ArrayList<String>();al.add("abc");al.add("hehe");ArrayList<Integer> al2 = new ArrayList<Integer>();al2.add(5);al2.add(67);printCollection(al);printCollection(al2);}/*** 迭代并打印集合中元素。* @param al*/public static void printCollection(Collection<?> al) {	//通配符的使用Iterator<?> it = al.iterator();while(it.hasNext()){System.out.println(it.next().toString());}}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

运行结果:
在这里插入图片描述

演示2:? extends E (上限)

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;import cn.itcast.p2.bean.Person;
import cn.itcast.p2.bean.Student;
import cn.itcast.p2.bean.Worker;public class GenericAdvanceDemo2 {/*** @param args*/public static void main(String[] args) {//创建3个ArrayList,分别存Worker,Student,StringArrayList<Worker> al = new ArrayList<Worker>();al.add(new Worker("Work",30));al.add(new Worker("Work",34));ArrayList<Student> al2 = new ArrayList<Student>();al2.add(new Student("stu1",11));al2.add(new Student("stu2",22));ArrayList<String> al3 = new ArrayList<String>();al3.add("stu3331");al3.add("stu33332");printCollection(al2);printCollection(al);//printCollection(al3);编译不通过 因为String不是Person的子类}/*** 迭代并打印集合中元素。* * 可以对类型进行限定:* ? extends E:接收E类型或者E的子类型对象。上限!* * ? super E :接收E类型或者E的父类型。下限!* @param al*/public static void printCollection(Collection<? extends Person> al) {//泛型的限定 只接收Person的子类Iterator<? extends Person> it = al.iterator();while(it.hasNext()){Person p = it.next();System.out.println(p.getName()+":"+p.getAge());}	}	
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

运行结果:
在这里插入图片描述

演示3:? super E(下限)

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;import cn.itcast.p2.bean.Person;
import cn.itcast.p2.bean.Student;public class GenericAdvanceDemo2 {/*** @param args*/public static void main(String[] args) {ArrayList<Person> al = new ArrayList<Person>();al.add(new Person("Person",30));al.add(new Person("Person",34));ArrayList<Student> al2 = new ArrayList<Student>();al2.add(new Student("stu1",11));al2.add(new Student("stu2",22));ArrayList<String> al3 = new ArrayList<String>();al3.add("stu3331");al3.add("stu33332");printCollection(al2);printCollection(al);//printCollection(al3);编译不通过 }//? super E :接收E类型或者E的父类型。下限!public static void printCollection(Collection<? super Student> al){Iterator<? super Student> it = al.iterator();while(it.hasNext()){System.out.println(it.next());}}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

运行结果:
在这里插入图片描述

上限的体现

一般在存储元素的时候都是用上限,因为这样取出都是按照上限类型来运算的。不会出现类型安全隐患。
比如TreeSet的addAll方法:
在这里插入图片描述

下限的体现

什么时候用下限呢?通常对集合中的元素进行取出操作时,可以使用下限。
例如:

class TreeSet<Worker>{Tree(Comparator<? super Worker> comp);}
  • 1
  • 2
  • 3
  • 4

常用对象API_01

82

常用对象API_01 1.Map集合 1.1 特点 存储的是键值对 必须保证键的唯一性 1.2 常用方法 1. 添加 ... 来自: qq_37118873