泛型
当将一个对象放入集合中,集合不会记住此对象的类型,当再次从集合中取出此对象时,改对象的编译类型变成了Object类型,但其运行时类型任然为其本身类型。
List<String> list=new ArrayList<>(); //<String>用于声明list中只能存放String类型的数据,如果类型不匹配则会编译失败
//list.add(new Random()) 语法报错,编译失败
list.add("abc");
String ss=list.get(0); //语法正确,不需要进行强制类型转换(窄化操作)
什么是泛型?
- 泛型是jdk5引入的类型机制,就是将类型参数化,它是早在1999年就制定的JSR14的实现。泛型作为一种安全机制而产生。
- 所谓类型参数化,是指用来声明数据的类型本身,也是可以改变的,它由实际参数来决定。在一般情况下,实际参数决定了形式参数的值。而类型参数化,则是实际参数的类型决定了形式参数的类型。
public void pp(String str){} //str实际上是形参
public void pp(Integer str){}
//调用时按照位置对应传入实际数据,实际数据叫做实参
pp("dddd")
定义方法:
public interface List<E> extends Collection<E>// 这里的<>中的内容就是类型参数,一般建议使用T或者
E之类的全大写
{
E get(int index);// 获取的元素类型就是定义时指定的类型
void add(E element);
}
List<String> list=new ArrayList<String>();
//list.add(new Random()) 编译失败,语法报错,因为E现在是String类型,不是Random
list.add("ddd");
//就是将String传递给E,用于替代定义中的E
String str=list.get(0); 不需要进行类型转换
List<Date> list=new ArrayList<>();//这里使用菱形语法,支持泛型推导
list.add("abc");//语法报错,编译时就会进行类型检查
list.add(123);//语法报错
list.add(new Date());
for(int i=0;i<list.size();i++){
Date temp=list.get(i); //获取数据不需要类型转换
System.out.println(temp.getYear()+1900);
}
泛型的好处:
1、可读性,从字面上就可以判断集合中的内容类型;
2 、类型检查,避免插入非法类型。
3 、获取数据时不在需要强制类型转换。
泛型类
定义:所谓泛型类generic class就是具有一个或多个类型参数的类
public class Generic<T>{
private T name;// 将T当做类型直接使用
}
public class 类型名<泛型名称列表>{
}
声明一个泛型类Generic,使用泛型的语法为<名称>,在类中就可以通过名称直接使用这个类型
public class Generic<T> {
private T name;
public T getName(){
return this.name;
}
public void setName(T name){
this.name=name;
}
}
如果编程中不使用泛型,使用集合会比较复杂:
ist list=new ArrayList();
list.add(123); //自动向上转型 int-->Integer-->Object
//获取数据还需要窄化操作
int kk=(Integer)list.get(0); //不进行类型判断,有可能出现ClassCastException
使用泛型,可以将运行时的类型检查搬到编译期实现;同时获取数据时不需要再编码进行类型转换
List<Integer> list=new ArrayList<>(); //从JDK1.7+支持泛型推导
list.add(123);
list.add(new Random());//编译报错
int kk=list.get(0); //不需要进行强制类型转换
泛型的例子:
public class Student<ID> {
private ID id;
public ID getId() {
return this.id;
}
public void setId(ID id) {
this.id=id;
}
}
//测试:
Student<String> s1=new Student<>();
// s1.setId(123); 编译报错,因为123不是String类型
s1.setId("123");
Student<Integer> s2=new Student<>();
// s2.setId("123");编译报错,因为"123"不是Integer类型
s2.setId(123);
声明一个泛型类Generic,使用泛型的语法规则为<名称>,在类中就可以通过名称直接使用这个类型
1 . 如果定义了泛型类,但是引用时不声明泛型值系统则识别泛型为Object类型
2.最后还需要注意:声明一个泛型实例时,传递给形参的实参必须是类类型,而不能使用int或char之类的简单类型。如果不传递类型,则系统默认类型为Object
带两个类型参数的泛型类
如果引用多个类型,可以使用逗号分隔:<S, D>;;类型参数名可以使用任意字符串,建议使用有代表意义的单个字符,以便于和普通类型名区分,如:T代表type,有源数据和目的数据就用S/D,子元素类型用E等。
泛型中的类型参数严格说明集合中装载的数据类型是什么和可以加入什么类型的数据