一、泛型的概念及意义
我对于泛型的理解就是在一种形式类型,可以类比于形式参数。
它的作用是在我们不清楚具体的类型时,做的一种形式定义。并且在这种定义下可以进行多种类型的定义。
二、泛型的作用域
泛型可以作用于:1.类 2.接口 3.方法;
1.泛型类
泛型类中最经典的就是各种容器类:set、list、map;
在这些类中提供了对不同类型的相同方法。
泛型类是在实例化类的时候指定泛型的具体类型;
下面定义一个简单的泛型类;
class demo<T>{
//定义一个T类型的变量;
private <T> a;
//利用构造器把传入的T类型变量赋值给a;
demo(T x){
a = x;
}
//将a的值返回;
public T geta(){
return a;
}
}
public class test{
public static void main(String[] args){
//没有为泛型类中的泛型传入实参
demo d1 = new demo();
//利用使用泛型的方法
demo<Integer> d2 = new demo<>(123);
int a = d2.geta();
}
}
在定义泛型类的派生类时不能继续使用泛型参数;
//例如这段代码就是错误的
class ext extends base<T>{}
可以使用一下方式定义派生类
//为泛型参数指定具体的实参;
class ext extends base<String>{}
//不带泛型定义的父类;
class ext extends base{}
2.泛型接口
泛型接口基本与泛型类一致;
下面定义一个简单的泛型接口
interface test<T>{
public <T> print(){}
}
class demo implements test<T>{
@override
public <T> print(){
return null;
}
}
3.泛型方法
在调用泛型方法的时候指定泛型的具体类型;
扫描二维码关注公众号,回复: 5789264 查看本文章
在fun1中是将一个泛型数组的元素添加到泛型集合中。
此时的泛型参数只需要是具有父子关系则不会出现异常。
在fun2中是将一个泛型集合的元素复制给另个集合。
此时的泛型参数只需要是具有父子关系则不会出现异常。
而在fun2中对于collection< T >来说只有T的类型完全相同才能复制。
所以我们利用了类型通配符并且设定了上限。
从而使得T类型的子类都可以复制给c2集合。
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
public class demo {
static <T> void fun1(T[] obj, Collection<T> collection) {
for (T o :
obj) {
collection.add(o);
}
for (T O :
collection) {
System.out.println(O);
}
}
static <T> void fun2(Collection<? extends T> c1, Collection<T> c2) {
for (T obj:
c1) {
c2.add(obj);
}
for (T obj:
c2) {
System.out.println(obj);
}
}
public static void main(String[] args) {
Collection<String> c1 = new ArrayList<>();
String[] strarr = new String[]{"1", "2", "3"};
//调用fun函数将strarr字符串数组中的元素添加到c1集合中
//fun1(strarr,c1);
Collection<Object> i1 = new HashSet<>();
Integer[] ints = new Integer[]{4, 5, 6};
//调用fun函数将ints的整形数组添加到i1的Object类型的集合中
//对于类型T来说只要是有父子接口实现关系就可进行使用;
//fun1(ints, i1);
ArrayList<String> list1 = new ArrayList<>();
ArrayList<Object> list2 = new ArrayList<>();
for (int i = 1; i <= 3; i++) {
String s = String.valueOf(i);
list1.add(s);
}
//将String类型的集合元素复制给Object类型的集合
fun2(list1,list2);
}
}
三、泛型通配符
类型通配符一般是使用?代替具体的类型实参,注意了,此处’?’是类型实参,而不是类型形参 。
可以解决当具体类型不确定的时候,这个通配符就是 ? ;当操作类型时,不需要使用类型的具体功能时,只使用Object类中的功能。那么可以用 ? 通配符来表未知类型。
例如下面的代码
public void showKeyValue1(Generic<Number> obj){
Log.d("泛型测试","key value is " + obj.getKey());
}
public void showKeyValue2(Generic<?> obj){
Log.d("泛型测试","key value is " + obj.getKey());
}
Generic<Integer> gInteger = new Generic<Integer>(123);
Generic<Number> gNumber = new Generic<Number>(456);
//此时传入Integer将会报错
//因为系统会判定为这是两个类型,和上面的fun2类似
showKeyValue1(gInteger);
//使用第二个方法时只要不使用到具体类型的方法则可以用“?”通配符
//此时将会返回正确的答案;
showKeyValue2(gInteger);