泛型总结
概述
泛型:JDK1.5出现的安全机制。
好处:1. 将运行时期的问题ClassCastException转移到变异时期。
2. 避免了强制转换的麻烦。
<>:什么时候用?当操作的引用数据类型不确定的时候。就是用<>。将要操作的引用数据类型传入即可。其实<>就是一个用于接收具体引用数据类型的参数范围。
在程序中,只要用到了带有<>的类或者接口,就要明确传入的具体引用数据类型。
泛型技术是给编译器使用的技术,用于编译时期,确保对了类型的安全。
擦除&补偿
泛型的擦除:运行时,会将泛型去掉,生成的class文件是不带泛型的,这个称为泛型的擦除。
为什么擦除呢?为了兼容运行的类加载器。
泛型的补偿:在运行时,通过获取元素的类型进行转换动作。不用使用者再强制转换了。
在集合中的应用
泛型类
class Tool<T> {
}
在JDK1.5后,使用泛型来接受类中要操作的引用数据类型。
泛型类。什么时候用?当类中操作的引用数据类型不确定的时候,就使用泛型来表示。
泛型方法
public <T> void show(T t) {
// ...
}
注意:
当方法是静态的,不能访问类上定义的泛型。如果静态方法要使用泛型,只能将泛型定义在方法上。
泛型接口
public class GenericDemo5 {
public static void main(String[] args) {
InterImpl in = new InterImpl();
in.show("abc");
InterImpl2<Integer> in2 = new InterImpl2<Integer>();
in2.show(3223);
}
}
/**
* 将泛型定义在接口上。
*/
interface Inter<T> {
public void show(T t);
}
class InterImpl implements Inter<String> {
public void show(String s) {
System.out.println(s);
}
}
class InterImpl2<Q> implements Inter<Q> {
public void show(Q q) {
System.out.println(q);
}
}
泛型限定(上限 下限 通配符)
通配符?:当不知道类型且不需要对该类型进行操作的时候,可以使用通配符。
上限 <? extends Person> 接收Person类型或者Person的子类型对象。
下限 <? super Student>接收Student类型或者Student的父类型。
一般在定义存元素的方法的时候用上限,因为这样都是按照上限类型来运算的,不会出现类型安全隐患。
通常对集合中的元素进行取出操作时,可以使用下限。
代码示例
package cn.itcast.p4.generic.define.demo;
/*public class Tool {
private Object object;
public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
}
}*/
//在jdk1.5后,使用泛型来接收类中要操作的引用数据类型。
//泛型类。什么时候用?当类中的操作的引用数据类型不确定的时候,就使用泛型来表示。
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);
}
}
package cn.itcast.p5.generic.advance.demo;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class GenericAdvanceDemo2 {
/**
* @param args
*/
public static void main(String[] args) {
ArrayList<Person> al = new ArrayList<Person>();
al.add(new Person("abc", 30));
al.add(new Person("abc4", 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);
}
/**
* 迭代并打印集合中元素。
*
* 可以对类型进行限定: ? extends E:接收E类型或者E的子类型对象。上限!
*
* ? super E :接收E类型或者E的父类型。下限!
*
* @param al
*/
/* public static void printCollection(Collection<? extends Person> al) {
Collection<Dog> al = new ArrayList<Dog>()
Iterator<? extends Person> it = al.iterator();
while (it.hasNext()) {
// T str = it.next();
// System.out.println(str);
// System.out.println(it.next().toString());
Person p = it.next();
System.out.println(p.getName() + ":" + p.getAge());
}
}*/
public static void printCollection(Collection<? super Student> al) {
Iterator<? super Student> it = al.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
//示例2(存储用上限):
package cn.itcast.p5.generic.advance.demo;
import java.util.ArrayList;
import cn.itcast.p2.bean.Person;
import cn.itcast.p2.bean.Student;
import cn.itcast.p2.bean.Worker;
public class GenericAdvanceDemo3 {
public static void main(String[] args) {
ArrayList<Person> al1 = new ArrayList<Person>();
al1.add(new Person("abc", 30));
al1.add(new Person("abc4", 34));
ArrayList<Student> al2 = new ArrayList<Student>();
al2.add(new Student("stu1", 11));
al2.add(new Student("stu2", 22));
ArrayList<Worker> al3 = new ArrayList<Worker>();
al3.add(new Worker("stu1", 11));
al3.add(new Worker("stu2", 22));
ArrayList<String> al4 = new ArrayList<String>();
al4.add("abcdeef");
// al1.addAll(al4);//错误,类型不匹配。
al1.addAll(al2);
al1.addAll(al3);
System.out.println(al1.size());
161
// printCollection(al2);
// printCollection(al);
}
}
/*
* 一般在存储元素的时候都是用上限,因为这样取出都是按照上限类型来运算的,不会出现类型安全隐患。
*/
class MyCollection<E> {
public void add(E e) {
}
public void addAll(MyCollection<? extends E> e) {
}
}
//示例3(取出元素用下限):
package cn.itcast.p5.generic.advance.demo;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
import cn.itcast.p2.bean.Person;
import cn.itcast.p2.bean.Student;
import cn.itcast.p2.bean.Worker;
public class GenericAdvanceDemo4 {
public static void main(String[] args) {
TreeSet<Person> al1 = new TreeSet<Person>(new CompByName());
al1.add(new Person("abc4",34));
al1.add(new Person("abc1",30));
al1.add(new Person("abc2",38));
TreeSet<Student> al2 = new TreeSet<Student>(new CompByName());
al2.add(new Student("stu1",11));
al2.add(new Student("stu7",20));
al2.add(new Student("stu2",22));
TreeSet<Worker> al3 = new TreeSet<Worker>();
162
al3.add(new Worker("stu1",11));
al3.add(new Worker("stu2",22));
TreeSet<String> al4 = new TreeSet<String>();
al4.add("abcdeef");
// al1.addAll(al4);//错误,类型不匹配。
// al1.addAll(al2);
// al1.addAll(al3);
// System.out.println(al1.size());
Iterator<Student> it = al2.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
}
/*
* class TreeSet<Worker>
* {
* Tree(Comparator<? super Worker> comp);
* }
*
* 什么时候用下限呢?通常对集合中的元素进行取出操作时,可以是用下限。
*
*/
class CompByName 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;
}
}
class CompByStuName implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
int temp = o1.getName().compareTo(o2.getName());
return temp==0? o1.getAge()-o2.getAge():temp;
}
}
class CompByWorkerName implements Comparator<Worker> {
@Override
public int compare(Worker o1, Worker o2) {
int temp = o1.getName().compareTo(o2.getName());
return temp==0? o1.getAge()-o2.getAge():temp;
}
}