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> {
@Override
public 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,String
ArrayList<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 1.Map集合 1.1 特点 存储的是键值对 必须保证键的唯一性 1.2 常用方法 1. 添加 ... 来自: qq_37118873