你好,游客 登录 注册 搜索
背景:
阅读新闻

Java静态泛型方法

[日期:2016-12-11] 来源:Linux社区  作者:dliyuedong [字体: ]

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中的泛型是伪泛型,但是泛型可以使代码更加的简洁,只是在使用 普通泛型方法 和 静态泛型方法 时需要特别注意类型转化。

本文永久更新链接地址http://www.linuxidc.com/Linux/2016-12/138197.htm

linux
相关资讯       Java静态泛型 
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数

       

评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款