泛型:JDK1.5版本以后出现的新特性,用于介乎额安全问题是一个安全机制。
好处:讲运行时出现的问题ClassCastException转移到了编译时,方便程序员解决问题
泛型格式:通过<>来指定要操作的引用数据
在使用JAVA提供的对象时什么时候使用泛型呢?
通常在集合框架中很常见,只要见到<>就要定义泛型
为了让不同的方法可以操作不同类型上,而且类型不确定,可以将泛型定义在方法上
静态方法不可以访问类上定义的方法
既可以定义泛型类也可以定义泛型方法;
泛型是提供java编译器使用的,可以先定集合中的输入类型,让编译器阻挡源程序的非法输入。
泛型中的术语:
ArrayList<E> 称为泛型类型
E 称为类型变量或类型参数
ArrayList<Integer> 称为参数化的类型
Integer 称为类型参数的实例或实际类型参数
ArrayList 称为原始类型
参数化类型与原始类型的兼容:
Collection<String> c = new Vector(); 编译器警告:
Collection c = new Vector<String>();
泛型中的通配符:(Collection<?> con);
?通配符定义的变量主要用作引用,可以调用与参数无关的方法,不能调用与参数有关的方法;
继承中的通配符: 注(Number 父类 Integer 子类)
上限 Vector<?extends Number> v = new Vector<Integer>();
当向集合中存储对象时,这个接收的集合参数使用上限
下限 Vector<?super Integer> v = new Vector<Number>();
当把集合中的元素拿出来时,比如(比较器)
类型参数的类型推断:
根据调用泛型方法时实际传递的参数类型和返回值类型来判断,具体规则如下:
==》当某个类型变量只在整个参数列表中的所有参数和返回值中一处被调用,根据调用方法时该处的
实际应用类型来确定。
例:swap(new String[3],3,4);-->static<E> void swap(E[]a,int i, int j);
==》当某个类型变量在整个参数列表中的所有参数和返回值中被多处调用,如果调用方法时,
这多处的实际应用类型都对应同一种类型来确定;
例: add(3,5);-->static<T> T add(T a, T b);
==》当某个类型变量在整个参数列表中的所有参数和返回值中被多处调用 ,如果调用方法时,
这多处的实际应用类型都对应不同类型,且没有使用返回值,这时候取多个参数中的最大交集类型
例:fill(new Integer[3], 3.5f); --> static<T> void fill<T[]a, T v>
==》当某个类型变量在整个参数列表中的所有参数和返回值中被多处调用 ,如果调用方法时,
这多处的实际应用类型都对应不同类型,且使用返回值,这时优先考虑返回值的类型;
例:int x = (3,3.5f); --> static<T> T add(T a, T b);
泛型定义的举例:
//自定义泛型类
<span style="font-size:18px;"><strong>public class Utils<QQ>{
private QQ q;
public void setObject(QQ q){
this.q = q;
}
public QQ getObject(){
return q;
}
}
public class Work {
}
public class UtilsDemo {
public static void main(String[] args) {
//创建带泛型类的对象
Utils<Work> u = new Utils<Work>();
u.setObject(new Work());
Work w = u.getObject();
//泛型定义在类上
new UtilsDemo.Demo<String>().show("ad");
//在泛型类中无定义泛型的方法和 类的类型一致
//new UtilsDemo().new Demo<Integer>().show("ad");
new UtilsDemo.Demo<Integer>().print(4); //泛型定义在方法上
new UtilsDemo().new Demo1().method('6');
new UtilsDemo().new Demo1().method("hello");
}
//内部类
static class Demo<T>{//泛型定义在类是类上
public void show(T t){
System.out.println(t);
}
public<Q> void print(Q q){//泛型定义在方法上
System.out.println(q);
}
public static <W> void show1(W w){//静态方法上自定义泛型
System.out.println(w);
}
}
class Demo1{
public<T> void method(T t){//泛型定义在方法上
System.out.println(t);
}
public<Q> void method1(Q q){
System.out.println(q);
}
}
} </strong></span>
泛型的应用:
<span style="font-size:18px;"><strong>public class Demo {
public static void main(String[] args) {
Map<String,String> map = new HashMap<String,String>();
map.put("abc", "123");
map.put("bcd", "234");
map.put("bad", "456");
map.put("acb", "000");
print(map);
}
private static void print(Map<String, String> map) {
//将映射关系取出放入Set集合中
Set<Map.Entry<String,String>> entrySet = map.entrySet();
//获取迭代
for(Iterator<Map.Entry<String,String>> it = entrySet.iterator(); it.hasNext(); ){
//获取所欲的映射关系
Map.Entry<String, String> me = it.next();
//用Map.Entry<String,String> 中的get方法获取键和值
String key = me.getKey();//获取键
String value = me.getValue();//获取值
System.out.println("key->" + key + "--->" + "value->" + value);
}
}
}
</strong></span>
通过反射获得泛型的实际参数类型:
<span style="font-size:18px;"><strong>import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Date;
import java.util.Vector;
/*
* 通过反射获得泛型的实际参数
*/
public class Demo {
public static void main(String[] args) throws Exception {
//通过反射获得方法
Method applyMethod = Demo.class.getMethod("applayVector", Vector.class);
//返回Type对象的数组
Type[] types = applyMethod.getGenericParameterTypes();
//参数化类型
ParameterizedType pType = (ParameterizedType)types[0];
//getRawType()返回声明此类型的类
System.out.println(pType.getRawType());
//getActualTypeArguments()表示此类型实际类型参数的 Type 对象的数组。
System.out.println(pType.getActualTypeArguments()[0]);
}
public static void applayVector(Vector<Date> v){
}
}
</strong></span>