泛型:安全机制。编译过后会被擦除。
思考题不会报错。因为参数化类型可以和原始类型是兼容的。
好处:
1,将运行时期出现的ClassCastException,转移到了编译时期。方便与程序员解决问题。
2,避免强制转换。
泛型的使用:
格式:通过<>来定义要操作的引用数据类型。读作typeof
使用java提供的对象时,什么时候使用泛型呢?
通常集合常见,见到<>就需要定义泛型。
泛型类:当类中操作的引用数据类型不确定的时候。早期用Object扩展,现在用泛型。
class Utils<Q>{
private Q q;
public void setObject(Q q){
this.q=q;
}
public Q getObject(){
return q;
}
}
泛型方法:泛型类定义泛型,在整个类中有效。如果方法被使用,那么泛型类的对象明确要操作的具体类型后,所有的操作就已经固定了。为了让不同方法可以操作不同类型,而且类型还不确定。那么可以将泛型定义在方法上。(定义在返回值前)
class Demo{
public <T>void show(T t){
}
public <Q>void print(Q q){
}
}
泛型在方法上定义只在方法中有效。不同方法的泛型互不干扰。
泛型类和泛型方法不冲突。
class Demo<T>{
public void show(T t){
}
public <Q>void print(Q q){
}
}
静态方法不可以访问类上定义的泛型,如果静态方法操作的引用数据类型不确定,可以将泛型定义在方法上。
泛型接口:
interface Inter<T>{
void show(T t);
}
class InterImpl<T> implements Inter<T>{
public void show(T t){
}
}
class InterImpl implements Inter<String>{
public void show(String t){
}
}
泛型的限定:
<?>通配符:只能调用对象中与参数化无关的方法。
<? extends E> 接收E和E的子类,上限。
<? super E> 接收E和E的父类,下限。
跳过泛型的检查:通过反射。
ArrayList<String> al = new ArrayList<String>();
al.getClass().getMethod("add",Object.calss).invoke(al,5);
此时可以将5存入集合。
注意:只有引用类型才能作为泛型方法的实际参数,对于add方法,使用基本类型的数据测试文有问题,这是因为自动装箱和拆箱,下面swa(new int[ ]{1,2,3},1,2);会报告编译错误,因为编译器不会把基本数据类型的int自动拆箱和装箱。因为new int[ ]本身就已经是一个对象了。你想要的可能就是int数组呢?
public class Text {
public static void main(String[] args) {
int[] arr=new int[]{1,3,4,5};
int n=5;
String[] s = new String[]{"haha","hehe","heihei"};
//交换数组中字符串的位置。
swap(s,1,2);
//swap(new int[]{1,2,3},3,5);编译错误
for(String s1:s){
System.out.println(s1);
}
swa(n);
}
public static <T> void swap(T[] a,int i,int j){
T tmp=a[i];
a[i]=a[j];
a[j]=tmp;
}
public static <T> void swa(T a){
System.out.println(a);
}
}
异常中泛型的应用:
private static <T extends Exception> sayHello() throws T
{
try{
}
catch(T e){
throw <T> e
}
}
![黑马程序员-泛型 - bb380667063 - Sun的博客 黑马程序员-泛型 - bb380667063 - Sun的博客](http://img0.ph.126.net/IWu7lcGj73GTg_zqvT6E7Q==/3380232995418587142.jpg)
通过反射获得参数的实际类型参数:
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 GenericTest {
public static void main(String[] args)throws Exception {
Vector<Date> v1=new Vector<Date>();
Method applyMethod=GenericTest.class.getMethod("applyVector",Vector.class);
Type[] types=applyMethod.getGenericParameterTypes();
ParameterizedType pType=(ParameterizedType)types[0];
System.out.println(pType.getRawType());//返回声明此类的原始类型的类或接口Vector
System.out.println(pType.getActualTypeArguments()[0]);//返回此类型实际参数化的类型,可能有多个,比如map集合。Date
}
public static void applyVector(Vector<Date> v1){
}
/*public static void applyVector(Vector<String> v1){
不是重载,去类型化。
}
*/
}