java----泛型
自定义泛型:
泛型只会在编译器存在,在运行期,会被擦除
泛型在类上定义,所以new一个对象的时候指定泛型类型,所以泛型必须和对象有关,和静态方法没有关系
public class Demo { public static void main(String[] args){ Node<String> str = new Node<String>("ddd"); Node<Integer> num = new Node<>(10); System.out.println(str); System.out.println(num); } } class Node<T>{ private T Date; private Node(){}; public Node(T Data){ this.Date = Data; } public T getDate() { return Date; } public void setDate(T date) { Date = date; } @Override public String toString() { return "Node{" + "Date=" + Date + '}'; } }
基本使用
import java.util.*; public class Demo { public static void main(String[] args){ Node<Number> num1 = new Node<Number>(20); Node<Integer> num2 = new Node<>(10); //Node.getData(num1); //不支持,不能进行转换 Node.getData(num2); Node.getData2(num1); //使用了通配符,既可 //此时泛型可以是Number包扩他的所有的子类 Node<Short> num3 = new Node<Short>((short) 11); Node.getData3(num1); Node.getData3(num3); //此时泛型可以是Byts包扩他的所有的父类 Node<Short> num4 = new Node<Short>((short) 11); Node.getData3(num1); Node.getData3(num4); //泛型方法定义 String arr[] = {"1","2","3"}; //好像不能传入一个集合 System.out.println(Arrays.toString(Node.fun(arr,1,2))); //泛型嵌套 Map<Integer,String> map = new HashMap<>(); map.put(1,"k"); map.put(2,"v"); map.put(3,"c"); Set<Map.Entry<Integer, String>> entries = map.entrySet(); for (Map.Entry entry:entries){ System.out.println(entry); } } } class Node<T>{ private T Date; private Node(){}; public Node(T Data){ this.Date = Data; } public T getDate() { return Date; } public void setDate(T date) { Date = date; } @Override public String toString() { return "Node{" + "Date=" + Date + '}'; } public static void getData(Node<Integer> node){ System.out.println(node.getDate()); } //使用通配符定义泛型类型,只能输出,不能修改 public static void getData2(Node<?> node){ //node.setDate(20); //报错 System.out.println(node.getDate()); } //设置上限,同样不能设置 public static void getData3(Node<? extends Number> node){ //node.setDate(20); //报错 System.out.println(node.getDate()); } //设置下限,包扩Byte,以及所有的父类 public static void getData4(Node<? super Byte> node){ //node.setDate(20); //报错 System.out.println(node.getDate()); } public static <T> T[] fun(T[] array,int i1,int i2){ T temp = array[i1]; array[i1] = array[i2]; array[i2] = temp; return array; } }
泛型的继承
class Test<T extends BaseEntity> 限制为了T (传入的)泛型必须继承BaseEntity,起到一部分的限制作用,为了不让T为任意的对象
可以通过查看HashMap源码来理解
public class Demo{ public static void main(String[] args) { HashMap<A, String> aStringHashMap = new HashMap<>(new HashMap<B,String>()); } } class A{} class B extends A{};
反射操作泛型
因为泛型在运行时就会被擦除,所以当一个类加载类内存的时候,就没有泛型了,反射直接读取泛型是读取不到的、
为了通过反射操作这些类型以迎合实际开发的需要,Java就新增了ParameterizedType,GenericArrayType,TypeVariable 和WildcardType几种类型来代表不能被归一到Class类中的类型但是又和原始类型齐名的类型。
ParameterizedType:表示一种参数化的类型,比如Collection <String>
GenericArrayType:表示一种元素类型是参数化类型或者类型变量的数组类型
TypeVariable:是各种类型变量的公共父接口
WildcardType:代表一种通配符类型表达式,比如?,?extends Number,?super Integer【wildcard是一个单词:就是“通配符"】
public class Test1 { public static void test01(Map<String,Integer> map){ } public static Map<String,Integer> test02(){ return null; } public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { Class<Test1> test1Class = Test1.class; Method test01 = test1Class.getDeclaredMethod("test01", Map.class); Type[] types = test01.getGenericParameterTypes(); for (Type t:types){ System.out.println(t); //java.util.Map<java.lang.String, java.lang.Integer> Type[] actualTypeArguments = ((ParameterizedType) t).getActualTypeArguments(); for (Type actualT:actualTypeArguments){ System.out.println(actualT); //class java.lang.String //class java.lang.Integer } } Method test02 = test1Class.getDeclaredMethod("test02"); Type genericReturnType = test02.getGenericReturnType(); System.out.println(genericReturnType); //java.util.Map<java.lang.String, java.lang.Integer> if (genericReturnType instanceof ParameterizedType){ Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments(); for (Type actualT:actualTypeArguments){ System.out.println(actualT); //class java.lang.String //class java.lang.Integer } } } }
泛型使用
功能1:调用方法,参数传入泛型,返回值
<T> T
表示返回值是一个泛型,传递啥,就返回啥类型的数据,而单独的T
就是表示限制你传递的参数类型,这个案例中,通过一个泛型的返回方式,获取每一个集合中的第一个数据, 通过返回值<T> T
和T
的两种方法实现
@Service public class RedisService { public <T> T get(KeyPrefix prefix, String token, Class<T> clazz) { Jedis jedis = null; try { String realKey = "xx"; String str = jedis.get(realKey); T t = stringToBean(str, clazz); return t; } finally { returnToPool(jedis); } } }
不传入泛型,返回类型是泛型
class B{ public static <T> List<T> list(){ List<T> list = null; return list; } public void c(){ //用什么类型接收T,存在问题 List<String> a = B.list(); List<Integer> b = B.list(); } }
功能2:限制传入类型
public class Demo2<T> { public static void main(String[] args) { //限制T 为String 类型 Demo2<String> demo = new Demo2<String>(); //获取string类型 List<String> array = new ArrayList<String>(); array.add("test"); array.add("doub"); String str = demo.getListFisrt(array); System.out.println(str); } private T getListFisrt(List<T> data) { if (data == null || data.size() == 0) { return null; } return data.get(0); } }
泛型
传入泛型,返回Boolean
public <T> Boolean set(KeyPrefix prefix, String key, T value) { return true; }