一个类如果好几个方法都用到了泛型,可以把它定义在类上,但是类上定义的泛型只对类的非静态成员有效。
因为调用静态方法不需要new对象,没有new对象在类上定义的泛型T就没有指定,在调用这个静态方法的时候,这个T是啥就没人知道。
package cn.mengmei.generic;
public class Demo1 <T> {
public void aa(T t){
}
public void bb(T t) {
}
public static <T> void cc(T t){
}
}
泛型方法复习:编写一个泛形方法,接收一个任意数组,并颠倒数组中的所有元素:
package cn.mengmei.generic;
import java.util.Arrays;
public class Demo2 {
public static void main(String[] args) {
Integer[] arr = new Integer[]{1,2,3,4,5};
System.out.println("原始:"+Arrays.asList(arr));
reverse(arr);
System.out.println("反转:"+Arrays.asList(arr));
}
public static <T> void reverse(T[] arr) {
for(int x=0, y=arr.length-1; x<y; x++,y--){
T temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
}
}
运行结果:
原始:[1, 2, 3, 4, 5]
反转:[5, 4, 3, 2, 1]
泛型类的典型应用(反射泛形)
- 如果一个类多处都要用到同一个泛型,这时可以把泛形定义在类上(即类级别的泛型),语法格式如下:
- public classGenericDao<T>{
- private T field1;
- public void save(T obj){}
- public T getId(int id){}
- }
- 注意,静态方法不能使用类定义的泛形,而应单独定义泛形。
- 泛形的典型应用:BaseDao和反射泛型
package cn.mengmei.generic;
import java.lang.reflect.ParameterizedType;
import org.hibernate.Session;
public abstract class BaseDao <T> {
private Session session;
private Class clazz;
//哪个子类调用这个方法,得到的clazz就是子类处理的类型(非常重要)
public BaseDao() { //反射泛型
ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass(); //BaseDao<Category> 参数化类型
clazz = (Class) pt.getActualTypeArguments()[0];
System.out.println(clazz);
}
public void add(T t){
session.save(t);
}
public T find(String id){
return (T) session.get(clazz, id);
}
public void update(T t){
session.update(t);
}
public void delete(String id){
T t = (T) session.get(clazz, id);
session.delete(t);
}
}
package cn.mengmei.generic;
import cn.mengmei.domain.Category;
public class CategoryDao extends BaseDao<Category>{
}
package cn.mengmei.generic;
import cn.mengmei.domain.Book;
public class BookDao extends BaseDao<Book>{
}
package cn.mengmei.generic;
import cn.mengmei.domain.Category;
public class Demo3 {
public static void main(String[] args) {
CategoryDao cDao = new CategoryDao();
BookDao bDao = new BookDao();
}
}
运行结果:
class cn.mengmei.domain.Category
class cn.mengmei.domain.Book
泛型的高级应用——通配符
- 当接收的类型不确定时,可以使用?通配符,?可以指向任何类型,如下所示:
- 此种形式下需要注意的是:由于?指向的是一种不确定的类型,因此不能调用与类型相关的方法,例如add()方法。
- 总结:使用?通配符主要用于引用对象,使用了?通配符,就只能调对象与类型无关的方法,不能调用对象与类型有关的方法。
package cn.mengmei.generic;
import java.util.ArrayList;
import java.util.Collection;
public class Demo4 {
public static void main(String[] args) {
print(new ArrayList<String>());
print(new ArrayList<Integer>());
}
public static void print(Collection<?> c) {
for(Object obj : c){
System.out.println(obj);
}
}
//当使用?通配符时,就不能再调用与类型相关的方法。
public static void save(Collection<?> c) {
//c.add("aa"); //编译通不过,因为不知道传进来的集合是什么类型的。
c.size();
}
}
泛型的高级应用——有限制的通配符
- 限定通配符的上边界:
- 限定通配符的下边界:
- 问题:以下代码行不行?