泛型
泛型
概念:泛型是为了提高代码的可读性,将错误尽量暴露在编译期间,泛型只会出现在编译期,编译后的字节码文件 中是没有泛型的。
泛型通配符
《E》 --Element 存放在集合中,因为集合中存放的就是元素
《T》 --Type Java类
《K》 --key值
《V》 --value值
《N》 --Number
《?》--不确定的java类型
泛型的作用
用在集合中
概念:泛型用在集合中,是为了约束集合中的元素
public static void main(String[] args) {
Map<String,String> map=new HashMap<String,String>();
}//该map中的key与value只能存入String类型的值
用在方法的参数中
public void sleep(List<Integer> list){
System.out.println(list.toString());
}
用在方法的返回值中
public List<String> sleep(List<Integer> list){
return null;
}
类型参数化
上述泛型的用途都好理解,但是如何理解将泛型使用在类或接口上呢?
在想要理解泛型是如何使用在类或接口上时,我们需要先理解,类型参数化这个概念!
类型参数化简单理解就是将类型也作为一个参数由外界传递进来。
举例来说就是,一个方法的参数类型,按照平常的写法,这个方法的参数类型都是固定的,但是通过泛型可以将这个类型参数化,类型由创建对象时传递过来的类型决定
泛型类
public class Test2 {
public static void main(String[] args) {
A<String> a=new A<String>();
a.method("1111");
A<Integer> b=new A<Integer>();
b.method(23);
}
}
class A<E> {
public void method(E e){
System.out.println(e);
}
}
泛型接口
public class Test2 {
public static void main(String[] args) {
C c=new C();
c.method("22222");
D d=new D();
d.method(23);
}
}
interface B<E>{
public void method(E e);
}
class C implements B<String>{
@Override
public void method(String s) {
System.out.println(s);
}
}
class D implements B<Integer>{
@Override
public void method(Integer integer) {
System.out.println(integer);
}
}
类型擦除
因为泛型只作用于编译期间,所以可通过反射来绕过泛型
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
List<Integer> list=new ArrayList<Integer>();
list.add(123);
//list.add("1231"); 被泛型约束
Class clazz=list.getClass();
//获取add方法
Method method = clazz.getDeclaredMethod("add",Object.class);
method.invoke(list,"1231");
System.out.println(list.get(1));
}//结果为1231