概述
集合是可以存放 任意 类型的对象,把对象存储到集合后,那么这时他们都会被 提升成 Object 类型。
当我们在 取出 每一个对象,并且进行相应的操作,这时必须采用 类型转换。
例子:
遍历list中元素的长度
public class GenericDemo {
public static void main(String[] args) {
List list = new ArrayList();
list.add("abc");
list.add(5);//由于集合没有做任何限定,任何类型都可以给其中存放
for(int i=0,len=list.size;i<size;i++)
//需要打印每个字符串的长度,就要把迭代出来的对象转成String类型
String str = (String) list.get(i);
System.out.println(str.length());
}
}
}
抛出异常:java.lang.ClassCastException
报错原因: 由于集合中什么类型的元素都可以存储
解决问题: 在JDK5之后,新增了 泛型(Generic)
泛型(Generics)
可以在 类 或 方法 中 限制类型
当没有指定泛型时,默认类型为 Object类型
好处
- 限制类型。将运行时期的ClassCastException,转移到了编译时期变成了编译失败。
- 不需要 类型强转
在集合中使用泛型
作用:
限制放数据的类型
取值时不需要 类型强转
例子:
List<String> list = new ArrayList<String>();
list.add("abc");
list.add("itcast");
// list.add(5);//当集合明确类型后,存放类型不一致就会编译报错
for(int i=0,len=list.size;i<size;i++)
String str = list.get(i);//不需要强转
System.out.println(str.length());
}
jdk7以后
在JDK 7后,右侧泛型的尖括号之内可以留空,但是<>仍然要写。简化格式:
ArrayList<String> list = new ArrayList<>();
理解
在类中使用泛型
表示 属性的类型、方法形参类型、方法返回值类型
格式
修饰符 class 类名<代表泛型的变量> { }
例子:
API中的ArrayList集合:
class ArrayList<E>{
public boolean add(E e){ }
public E get(int index){ }
....
}
符号<E>的含义
这里的<E> ,表示一种指定的数据类型,叫做泛型。 E 取自Element(元素)的首字母。
在构造ArrayList对象时, <E>指定了什么数据类型,那么 add(E e) 方法中,只能添加什么数据类型的对象。
符号<T>的含义
泛型有时也用到<T>,T 取自 Type的首字母,表示传输参数的类型。
用法与 <E> 相同
创建对象的时候指定泛型
例如:ArrayList<String> list = new ArrayList<String>();
此时,变量E的值就是String类型,那么我们的类型就可以理解为:
例子
public class MyGenericMethod<T> {
public void show(T t) {
System.out.println(t);
}
public static void main(String[] args) {
//创建对象时,指定泛型
MyGenericMethod<Student> m=new MyGenericMethod();
Student std=new Student();
m.show(std);
}
}
Student为演示类,空类
在方法中使用泛型
格式
修饰符 <代表泛型的变量> 返回值类型 方法名(参数){
}
例如:
public class MyGenericMethod {
//方法上的```<T>``` 代表要用到泛型参数
public <T> void show(T t) {
System.out.println(t);
}
public static void main(String[] args) {
MyGenericMethod m=new MyGenericMethod();
Student std=new Student();
//调用方法时,确定泛型的类型
m.show(std);
}
}
Student类为演示类,空类
方法上的<T> 代表括号里面要用到泛型参数(在类名后没定义泛型,此处必须定义泛型)
调用方法时,确定泛型的类型
在接口中使用泛型
格式
修饰符 interface 接口名 <代表泛型的变量> {
}
例如:
public interface MyGenericInterface<E>{
public abstract void add(E e);
public abstract E getE();
}
使用格式:
1、定义类时确定泛型的类型
例如
public class MyImp1 implements MyGenericInterface<String> {
@Override
public void add(String e) {
// 省略...
}
@Override
public String getE() {
return null;
}
}
此时,泛型E的值就是String类型。
2、始终不确定泛型的类型,直到创建对象时,确定泛型的类型
例如
public class MyImp2<E> implements MyGenericInterface<E> {
@Override
public void add(E e) {
// 省略...
}
@Override
public E getE() {
return null;
}
}
确定泛型:
/*
* 使用
*/
public class GenericInterface {
public static void main(String[] args) {
MyImp2<String> my = new MyImp2<String>();
my.add("aa");
}
}
