泛型的引入
集合可以添加任意类型,所以如果往容器中添加不同的类型,例如String类型和Integer类型,在遍历的时候如果希望访问子类元素所特有的方法,由于元素是Object类型,所以需要向下转型,这个时候如果没有对Object的所有子类做判断,安全隐患永远存在。例如:
Collection c = new ArrayList();
c.add(“三国演义”);
c.add(“西游记”);
c.add(“红楼梦”);
c.add(“隔壁老王”);
c.add(25);
for (Object obj : c) {
// System.out.println(obj);
// 如果我想要使用 元素子类所特有的方法 例如 String的length方法
String s = (String) obj;
System.out.println(s + “|” + s.length());
}
抛出如下异常:java.lang.ClassCastException
针对所有的子类使用instanceof做逐一判断,但是又有新的问题,容器可以添加任意类型,如果又来一个学生类,又需要添加elseif语句,不满足开闭原则
for (Object obj : c) {
if (obj instanceof String) {
String s = (String) obj;
System.out.println(s + "|" + s.length());
} else if (obj instanceof Integer) {
Integer ii = (Integer) obj;
System.out.println(ii + "|" + ii.intValue());
}
Java提供了泛型
泛型是模仿方法和数组而来的。
数组的特点:
数组在编译时期确定类型
方法的特点:参数化类型
泛型的概述
JDK1.5之后引入的新特性,泛型是一种将类型的确定提前到编译时期的一种参数化类型
格式
<E>
泛型的特点:
1.泛型具备传递性
2.泛型可以定义多个
3.泛型只能设置引用数据类型
4.泛型命名可以是A~Z之间
泛型的分类
泛型类: 把泛型定义在类上
泛型接口: 把泛型定义在接口上
泛型方法: 把泛型定义在方法上
泛型的好处:
1.消除了黄色警告线
2.去除类型转换,提高了效率
3.提高了安全性,避免了类型转换异常
4.简化了代码
5.提高了代码的扩展和可维护性
代码实例:
Collection<String> c = new ArrayList<String>();
c.add("三国演义");
c.add("西游记");
c.add("红楼梦");
c.add("隔壁老王");
Iterator<String> it = c.iterator();
while (it.hasNext()) {
String s = it.next();
System.out.println(s + "|" + s.length());
}
for (String s : c) {
System.out.println(s);
}
泛型类
概述: 把泛型定义在类上
在JDK1.5之前的做法
class GenericClass {
private Object object;
public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
}
}
在JDK1.5之后引入泛型
class GenericClass<E> {
private E e;
public E getObject() {
return e;
}
public void setObject(E e) {
this.e = e;
}
}
使用实例:
GenericClass<String> gc = new GenericClass<String>();
gc.setObject("abc");
// gc.setObject(18);
/*Object obj = gc.getObject();
if (obj instanceof String) {
String s = (String) obj;
System.out.println(s + "|" + s.length());
}*/
String s = gc.getObject();
System.out.println(s + "|" + s.length());
多个泛型定义的泛型类:
class GenericClass<E, T, H> {
private E e;
private T t;
private H h;
public E getE() {
return e;
}
public void setE(E e) {
this.e = e;
}
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
public H getH() {
return h;
}
public void setH(H h) {
this.h = h;
}
}
泛型接口
概述:把泛型定义在接口上
使用泛型接口的三种方式:
1.在实现类的时候确定泛型类型
2.在实现类的时候不确定泛型类型,在创建接口的时候确定泛型类型
3.在匿名内部类的时候使用泛型
在实现类的时候确定泛型类型
interface IGenericInterface<E, T> {
void show(T t);
void concat(E e, T b);
}
class GenericInterfaceImpl implements IGenericInterface<String, Integer> {
@Override
public void show(Integer t) {
System.out.println(t);
}
@Override
public void concat(String e, Integer b) {
System.out.println(e + b);
}
}
在实现类的时候不确定泛型类型,在创建接口的时候确定泛型类型
class GenericInterfaceImpl2<E, T> implements IGenericInterface<E, T> {
@Override
public void show(T t) {
System.out.println(t);
}
@Override
public void concat(E e, T b) {
System.out.println(e);
System.out.println(b);
}
}
IGenericInterface<String,Integer>gi=newGenericInterfaceImpl2<>();
在匿名内部类的时候使用泛型
IGenericInterface<String, Integer> gi = new IGenericInterface<String, Integer>() {
@Override
public void show(Integer t) {
System.out.println(t);
}
@Override
public void concat(String e, Integer b) {
System.out.println(e + b);
}
};
gi.show(100);
gi.concat("abc", 200);
泛型方法
概述: 把泛型定义方法上
使用泛型方法: 在方法调用的时候确定泛型
特点:
1.泛型方法在方法调用的时候确定类型
2.泛型方法独立于泛型类,泛型方法又称为局部泛型
3.泛型方法也可以定义多个
泛型的应用:
为什么泛型中的 toArray 设计成一个泛型方法?
因为设计者并不知道用户往容器中添加什么类型的元素,所以设计为泛型,由调用者确定返回值类型,自己接收
代码示例
Collection<String> c = new ArrayList<>();
c.add("abc");
c.add("efg");
c.add("hij");
// 将集合转换成数组
String[] strs = c.toArray(new String[] {});
for (String s : strs) {
System.out.println(s);
}
// 将数组转换成集合 T[]
Integer[] is = {11, 22, 33, 44};
List<Integer> list = Arrays.asList(is);
for (Integer ii : list) {
System.out.println(ii);
}
泛型限定符
<?> : 代表任意类型
<? extends E>: 代表泛型可以是E类型或者E的子类
<? super T>: 代表泛型可以是 T类型或者是 T 的父类
代码示例
Collection<?> c1 = new ArrayList<String>();
Collection<?> c2 = new ArrayList<Fu>();
Collection<?> c3 = new ArrayList<Son>();
Collection<?> c4 = new ArrayList<Daughter>();
Collection<?> c5 = new ArrayList<Object>();
Collection<? extends Fu> c6 = new ArrayList<Fu>();
Collection<? extends Fu> c7 = new ArrayList<Son>();
Collection<? extends Fu> c8 = new ArrayList<Daughter>();
// Collection<? extends Fu> c9 = new ArrayList<Object>();
Collection<? super Fu> c10 = new ArrayList<Fu>();
// Collection<? super Fu> c11 = new ArrayList<Son>();
// Collection<? super Fu> c12 = new ArrayList<Daughter>();
Collection<? super Fu> c13 = new ArrayList<Object>();
// boolean addAll(Collection<? extends E> c)
Collection<Fu> c = new ArrayList<>();
Collection<? extends Fu> cc = new ArrayList<Son>();
Collection<? extends Fu> cc2 = new ArrayList<Daughter>();
c.addAll(cc);
c.addAll(cc2);
泛型嵌套
概述: 泛型里面定义泛型
需求: 存储如下数据格式:
一共有三个班
A班有三个学生
B班有两个学生
C班有一个学生
Collection<Student> ac = new ArrayList<Student>();
ac.add(new Student("张三", 30));
ac.add(new Student("李四", 35));
ac.add(new Student("王五", 40));
Collection<Student> bc = new ArrayList<Student>();
bc.add(new Student("赵六", 30));
bc.add(new Student("孙七", 35));
Collection<Student> cc = new ArrayList<Student>();
cc.add(new Student("隔壁老王", 30));
Collection<Collection<Student>> classes = new ArrayList<Collection<Student>>();
classes.add(ac);
classes.add(bc);
classes.add(cc);
/*Iterator<Collection<Student>> iterator = classes.iterator();
while (iterator.hasNext()) {
Collection<Student> c = iterator.next();
Iterator<Student> it = c.iterator();
while (it.hasNext()) {
Student s = it.next();
System.out.println(s.getName() + "|" + s.getAge());
}
}*/
for (Collection<Student> collection : classes) {
for (Student s : collection) {
System.out.println(s.getName() + "|" + s.getAge());
}
}