java泛型
java泛型
JinJava 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型
泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数
举例:在集合中使用泛型
@Test
public void test1(){
// <Integer> 规定 list 集合里只能放 integer 类型的元素
ArrayList<Integer> list = new ArrayList<>();
// 自动装箱 Integer类型
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
// error 类型不匹配
// list.add("aa");
// 在 map 使用
HashMap<Integer,String> map = new HashMap<>();
map.put(1,"aa");
map.put(2,"bb");
// error 类型不匹配
// map.put(2,"cc");
}
泛型方法
规则:
泛型方法中的泛型参数在方法被调用时确定
泛型方法可以根据需要,声明为 static 的
泛型方法体的声明和其他方法一样。注意类型参数只能代表引用型类型,不能是原始类型(像 int、double、char 等)
泛型方法的格式:
[访问权限] <泛型> 返回值类型 方法名([泛型标识 参数名称]) [抛出的异常]{ //方法体 }
java 中通常的泛型标记符:
- E - Element (在集合中使用,因为集合中存放的是元素)
- T - Type(Java 类)
- K - Key(键)
- V - Value(值)
- N - Number(数值类型)
- ? - 表示不确定的 java 类型
举例:打印数组
public static <E> void printArr(E[] Arr){
// 输出数组元素
for ( E element : inputArray ){
System.out.printf( "%s ", element );
}
System.out.println();
}
public static void main( String args[] )
{
// 创建不同类型数组: Integer, Double 和 Character
Integer[] intArray = { 1, 2, 3, 4, 5 };
Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };
Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };
System.out.println( "整型数组元素为:" );
printArr( intArray ); // 传递一个整型数组
System.out.println( "\n双精度型数组元素为:" );
printArr( doubleArray ); // 传递一个双精度型数组
System.out.println( "\n字符型数组元素为:" );
printArr( charArray ); // 传递一个字符型数组
}
举例:指定位置交换数组元素
public static <E> void swapArr(E[] arr,int a,int b){
E temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
泛型类
当我们在类或接口中定义某个成员时,该成员的相关类型是不确定的,而这个 类型需要在使用这个类或接口时才可以确定
泛型类的声明和非泛型类的声明类似,除了在类名后面添加了类型参数声明部分
格式:
【修饰符】 class 类名<类型变量列表> 【extends 父类】 【implements 接口们】{}
举例:
class Person<T> {
// 使用 T 类型定义变量
private T info;
// 使用 T 类型定义一般方法
public T getInfo() {
return info;
}
public void setInfo(T info) {
this.info = info;
}
// 使用 T 类型定义构造器
public Person() {
}
public Person(T info) {
this.info = info;
}
}
@Test
public void test(){
Person<String> p1 = new Person<>(new String("java"));
Person<Integer> p2 = new Person<>(new Integer(10));
String info1 = p1.getInfo(); // java
Integer info2 = p2.getInfo(); // 10
}
继承上的关系:
- 类SuperA是类A的父类,则
G<SuperA>
与G<A>
的关系:G<SuperA>
和G<A>
是并列的两个类,没有任何子父类的关系。
比如:ArrayList<Object>
、ArrayList<String>
没有关系
- 类SuperA是类A的父类或接口,
SuperA<G>
与A<G>
的关系:SuperA<G>
与A<G>
有继承或实现的关系。
即A<G>
的实例可以赋值给SuperA<G>
类型的引用(或变量)
比如:List<String>
与 ArrayList<String>
通配符的使用
1、类型通配符一般是使用 ? 代替具体的类型参数。例如 List<?>
在逻辑上是 List<String>
,List<Integer>
等所有 List<具体类型实参> 的父类
通配符的读与写
读取数据:允许的,读取的值的类型为Object类型
写入数据:不允许的。特例:写入null值。
// error
Collection<?> c = new ArrayList<String>();
c.add(new Object());
有限制的通配符
- 通配符指定上限:
<? extends 类/接口>
- 通配符指定下限:
<? super 类/接口>
说明:
<? extends Number> //(无穷小 , Number]
//只允许泛型为 Number 及 Number 子类的引用调用
<? super Number> //[Number , 无穷大)
//只允许泛型为 Number 及 Number 父类的引用调用
<? extends Comparable>
//只允许泛型为实现 Comparable 接口的实现类的引用调用
参考资料
评论
匿名评论隐私政策
✅ 你无需删除空行,直接评论以获取最佳展示效果