Java静态泛型技巧
发布时间:2021-12-10 13:34:44 所属栏目:PHP教程 来源:互联网
导读:Java在JDK 5中引入了泛型,使用起来方便了很多,下面是一段很常见的泛型使用: ListString list = new ArrayListString(); 泛型方法使用 不仅集合中可以使用,在定义类、接口和方法的时候也是经常使用的,但是关于泛型方法使用的场景还是不太多。下面从求两
Java在JDK 5中引入了泛型,使用起来方便了很多,下面是一段很常见的泛型使用: List<String> list = new ArrayList<String>(); 泛型方法使用 不仅集合中可以使用,在定义类、接口和方法的时候也是经常使用的,但是关于泛型方法使用的场景还是不太多。下面从求两个数的最大数的实现上来看一下泛型类和泛型方法的简单使用: 泛型类(接口) package me.codeboy.test; /** * generic test * Created by yuedong on 9/12/16. */ public class MathTest<T extends Comparable> { public static void main(String[] args) { MathTest<Integer> mathTest1 = new MathTest<Integer>(); MathTest<Double> mathTest2 = new MathTest<Double>(); System.out.println(mathTest1.max(1, 2)); System.out.println(mathTest2.max(2.0, 3.0)); } private T max(T t1, T t2) { return t1.compareTo(t2) > 0 ? t1 : t2; } } 泛型方法 /** * generic test * Created by yuedong on 9/12/16. */ public class MathTest { public static void main(String[] args) { MathTest mathTest = new MathTest(); System.out.println(mathTest.max(1, 2)); System.out.println(mathTest.max(2.0, 3.0)); } private <T extends Comparable> T max(T t1, T t2) { return t1.compareTo(t2) > 0 ? t1 : t2; } } 静态泛型方法 /** * generic test * Created by yuedong on 9/12/16. */ public class MathTest { public static void main(String[] args) { System.out.println(max(1, 2)); System.out.println(max(2.0, 3.0)); } private static <T extends Comparable> T max(T t1, T t2) { return t1.compareTo(t2) > 0 ? t1 : t2; } } 泛型方法优缺点 优点很明显,代码简洁多了,或者可以说比普通的泛型泛型更为简洁,网上有一段关于Android中频繁使用 findViewById 方法的静态泛型方法实现,被称为见过最牛逼的Android代码,但是事物都有两面性,静态泛型方法也有相应的缺点,再看一段代码: import java.util.ArrayList; import java.util.List; /** * test entry * Created by yuedong on 9/10/16. */ public class Test { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("test"); //普通转换 ArrayList<String> result1 = (ArrayList<String>) list; //静态泛型转换 String result2 = convert(list); } private static <T> T convert(Object a) { return (T) a; } } 上述代码是 编译通过,运行异常,为什么会出现这种现象呢?这是因为Java的泛型方法属于伪泛型,在编译的时候将进行类型擦除。普通的泛型方法在类构建时已经明确制定了对应的类型,而在静态泛型方法中,类型是无法直接推测的,缺少了明确的类型,最终造成类型转化异常。 Exception in thread "main" java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.lang.String 原理探索 看到了上面的结果,不禁想了解下泛型方法在类型擦除后最终转换成了什么,反编译上述静态泛型方法编译后的class文件如下: Compiled from "Test.java" public class Test { public Test(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: new #2 // class java/util/ArrayList 3: dup 4: invokespecial #3 // Method java/util/ArrayList."<init>":()V 7: astore_1 8: aload_1 9: ldc #4 // String test 11: invokeinterface #5, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z 16: pop 17: aload_1 18: checkcast #2 // class java/util/ArrayList 21: astore_2 22: aload_1 23: invokestatic #6 // Method convert:(Ljava/lang/Object;)Ljava/lang/Object; 26: checkcast #7 // class java/lang/String 29: astore_3 30: return } 可以看到convert函数最终转化后对应的字节码为 Method convert:(Ljava/lang/Object;)Ljava/lang/Object; 参数为Object类型,返回也为Object类型,而在接下来的 checkcast 操作中,由于 List 和 String 类型的不同,所以抛出了异常。 private static <T extends List> T convert(Object a) { return (T) a; } 对于上述的代码反编译后对应 Method convert:(Ljava/lang/Object;)Ljava/util/List; 中,可以看到此时参数为Object类型,返回为List类型。 小结 尽管Java中的泛型是伪泛型,但是泛型可以使代码更加的简洁,只是在使用 普通泛型方法 和 静态泛型方法 时需要特别注意类型转化。 ![]() (编辑:应用网_丽江站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |