Java的基础语法可以看尚硅谷的这个PDF:尚硅谷JavaSE基础/《Java从入门到精通(JDK17版)》_尚硅谷电子书.pdf · Autism_Btkrsr/Blog_md_to_pdf - 码云 - 开源中国 (gitee.com)
回答重点
Java泛型的作用是通过在编译时检查类型安全,允许程序员编写更通用和灵活的代码,避免在运行时发生类型转换错误。
总结作用:
- 类型安全:泛型允许在编译时进行类型检查,确保在使用集合或其他泛型类时,不会出现类型不匹配的问题,减少了运行时的ClassCastException错误
- 代码重用:泛型使代码可以适用于多种不同的类型,减少代码重复,提升可读性和可维护性
- 消除显式类型转换:泛型允许在编译时指定类型参数,从而消除了运行时需要显式类型转换的麻烦
List<String> list = new ArrayList<>();
list.add("Hello");
String str = list.get(0); // 不需要类型转换
扩展知识
泛型的实际应用
- 集合框架:Java的集合框架广泛使用了泛型。List<T>、Set<T>和Map<K, V>等接口可以针对不同的数据类型实现统一的操作
- 泛型方法:不仅可以定义泛型类,还可以定义泛型方法,使得方法能够处理多种不同的数据类型
- 泛型方法
可以显式指定类型,不指定的话,Java编译器会自动推断类型
public class GenericMethodTest {
public static void main(String[] args) {
Integer[] intArr = {1, 2, 3, 4, 5};
Double[] doubleArr = {1.1, 2.2, 3.3, 4.4, 5.5};
String[] stringArr = {"Hello", "World"};
printArray(intArr);
// 显式指定类型
GenericMethodTest.<Integer>printArray(intArr);
printArray(doubleArr);
printArray(stringArr);
// 多类型参数
new GenericMethodTest().printMultiArgsArray(intArr, stringArr);
}
public static <T> void printArray(T[] arr){
for (T element: arr){
System.out.print(element);
}
System.out.println();
}
// 多类型参数
public <T, V> void printMultiArgsArray(T[] keys, V[] values){
for (int i = 0; i < Math.min(keys.length, values.length); i++){
System.out.printf("{Key:%s,Value:%s}\n", keys[i], values[i]);
}
}
}
为什么需要泛型?
在Java5之前是没有泛型的,没泛型都能用的好好的,为什么非要加个泛型呢?能解决什么问题呢?
看这段代码
List list = new ArrayList();
list.add("yes"); // 加入string
list.add(233); // 加入int
在没有泛型的时候,加入的集合的数据并不会做任何约束,都会被当做成Object类型。
可能有人说:这很好呀,多自由!确实,自由是挺自由,但是代码的约束力越低,越容易从出错,使用上也有诸多不便。比如获取的时候老是要强转
就算强转过了编译器这一关,运行的时候还是会报错
综上,Java就引入了泛型。
所以泛型的作用就是加了一层约束,约束了类型。
有了这一层约束就好办事了,由于声明了类型,可以在编译时就识别不出准确的类型元素。使得错误提早抛出,避免运行时才发现。
小结一下泛型的好处:
- 提高了代码的可读性,一眼就能看出集合的类型
- 可在编译期检查类型的安全,增加程序的健壮性
- 省心不需要强转(其实内部帮做了强转,下面会说)
- 提高代码的复用率,定义好泛型,一个方法(类)就能适配所有类型(其实以前Object也行,就是比较麻烦)
为什么Java的泛型是伪泛型?
public class GenericReflectionTest {
public static void main(String[] args) throws Exception{
List<String> list = new ArrayList<>();
list.add("Hello");
list.getClass().getMethod("add", Object.class).invoke(list, 123);
System.out.println(list);
}
}
可以看到,我声明的是一个String类型的集合,但是通过反射往集合中插入了int类型的数据,居然成功了?
这说明在运行的时候泛型根本没起作用!也就是说在运行的时候JVM获取不到泛型的信息,也不会对其做任何约束
可以认为Java的泛型就是编译时失效,运行的时候就是没有泛型,所以大家才说Java是伪泛型!
因此,实际上在运行的时候泛型的类型是被擦除的
总结:Java的泛型只在编译时生效,JVM运行时没有泛型
关于反射的博客,看我这一篇:【Java】反射_反射 博客园-CSDN博客