函数对象:
package test;
import java.util.Collection;
import java.util.Comparator;
/**
* CaseInsensitiveCompare 就是函数对象
* 具体使用是在main方法中的System.out.println(findMax(arr,new CaseInsensitiveCompare()));
* @author Administrator
*
*/
public class GenericMemoryCell {
public static <AnyType> AnyType findMax(AnyType[] arr, Comparator<? super AnyType> cmp){
int maxIndex = 0;
for(int i=1; i<arr.length; i++){
if(cmp.compare(arr[i], arr[maxIndex]) > 0 ){
maxIndex = i;
}
}
return arr[maxIndex];
}
public static void main(String[] args) {
String[] arr = {"ZEBRA","alligator","crocodile"};
System.out.println(findMax(arr,new CaseInsensitiveCompare()));
}
}
class CaseInsensitiveCompare implements Comparator<String>{
@Override
public int compare(String o1, String o2) {
// TODO Auto-generated method stub
return o1.compareToIgnoreCase(o2);
}
}
T代表泛型
?是通配符,不能用于声明阶段
使用泛型的一个比较大的作用是方便简单并且避免了数组的类型兼容性导致的问题而且将运行时异常提前到了编译时异常。
比如,在泛型之前如果要达到泛型的目的,可以使用Object和接口两种形式:
使用Object的一个问题是需要强制类型转换。写入的时候先转换成了object然后读出的时候仍然是object因此要做强制类型转换。
使用接口形式:
这种方式必须要求传递的对象实现相应的接口,
数组类型的兼容性:
设Employee IS-A Person,那么是不是也意味着Employee[] IS-A Person[],换句话说如果一个程序接收Person[]作为参数,那么能不能将Emplyee[]
作为参数传递?实际上是可以的,但是还有一种比较复杂的情况,假设除了Employee外还有Student IS-A Person,此时考虑下面两条复制语句:
Person[] arr = new Eemployee[5];
arr[0] = new Student(...);
两句都能编译,而实际上arr[0]引用了一个Employee,可是Student IS-NOT-A Employee,这样就产生了混乱。运行时也不报错因为不存在类型转换。
比如上例中的接口形式的代码。
使用泛型时
在第五行,例如类GenericMemoryCell<String>的write方法需要一个String,传入其他类型将产生一个编译错误。
也可以声明接口是泛型的比如Comparable,在java5之前不是泛型的他的compareTo方法接收一个Objet作为参数,因此传递给他的参数即使不是个
合理的类型也会编译,只是在运行的时候报ClassCaseException。但是使用泛型的话在编译器就能提示处错误。
泛型集合不具有类型兼容性
可以使用通配符来实现如上要求
通配符可以不带任何限制使用比如<?>相当于<? extends Object> 或者用super来标识超类而非子类
泛型方法:
有下列原因使用泛型方法: