大白话说Java泛型(一):入门、原理、使用

小说:猪八戒打码下载安装作者:董密平更新时间:2019-04-22字数:23921

尽管安禄山已经遭受了沉重的打击,但最后致命的一刀却是在天大亮后袭来,他接到了消息,李亨和陈玄礼去拜访了千牛卫军衙,五百名金吾卫士兵全部获释,每个人还喝了压惊酒,高高兴兴走了,但他的三十几名手下却全部被斩首,人头悬挂在怀远坊内。

一品威客接单要花钱吗

紫妍虽然只是斗宗,但是身为太虚古龙与生俱来的对空间有着同级别强者无法比拟的天赋,所以还是能为云韵解答。
趁着炮弹爆炸的瞬间,脑袋上缠着白布条的鬼子敢死队嚎叫着向阵地发起了冲锋,阵地上没有人想这批鬼子打来反击的枪弹,后面的渡边鬼子以为阵地上的那些中国兵已经被自己刚才的那阵迫击炮炮弹给炸晕了,便有些得意起来,心想这一阵敢死队冲杀上去,阵地上的那些支那军士兵估计没剩下来几个的了,即使有,也必被冲上去的皇军敢死队给杀死!

但是这一股气运对于普通人而言当然很惊人,福缘深厚得很,但是对于修道者而言真的不算什么,只能一点一滴的积累起来。

文章首发于【博客园-陈树义】,点击跳转到原文《大白话说Java泛型(一):入门、原理、使用》

远在 JDK 1.4 版本的时候,那时候是没有泛型的概念的。当时 Java 程序员们写集合类的代码都是类似于下面这样:

List list = new ArrayList();
list.add("www.cnblogs.com");
list.add(23);
String name = (String)list.get(0);
Integer number = (Integer)list.get(1);

在代码中声明一个集合,我们可以往集合中放入各种各样的数据,而在取出来的时候就进行强制类型转换。

但其实这样的代码存在一定隐患,因为可能过了不久我们就会忘记到底我们存放的 list 里面到底第几个是 String,第几个是 Integer 了。这样就会出现下面这样的情况:

List list = new ArrayList();
list.add("www.cnblogs.com");
list.add(23);
String name = (String)list.get(0);
String number = (String)list.get(1);    //ClassCastException

上面的代码在运行时会发生强制类型转换异常。这是因为我们在存入的时候,第二个是一个 Integer 类型,但是取出来的时候却将其强制转换为 String 类型了。

泛型的诞生

Sun 公司为了使 Java 语言更加安全,减少运行时异常的发生。于是在 JDK 1.5 之后推出了泛型的概念。

于是在 JDK 1.5 之后,我们如果使用集合来书写代码,可以使用下面这种形式:

List<String> list = new ArrayList();
list.add("www.cnblogs.com");
list.add("www.cnblogs.com/chanshuyi");
String cnBlogs = list.get(0);
String myWebSite = list.get(1); 

泛型就是将类型参数化,其在编译时才确定具体的参数。在上面这个例子中,这个具体的类型就是 String。可以看到我们在创建 List 集合的时候指定了 String 类型,这就意味着我们只能往 List 集合中存放 String 类型的数据。而当我们指定泛型之后,我们去取出数据后就不再需要进行强制类型转换了,这样就减少了发生强制类型转换的风险。

上面我们通过两个很简单的例子知道了为什么要有泛型,以及泛型最简单的使用。下面我们通过一个面试中常见的例子来看一下泛型的本质是什么。

泛型的本质

ArrayList<String> a = new ArrayList<String>();
ArrayList<Integer> b = new ArrayList<Integer>();
Class c1 = a.getClass();
Class c2 = b.getClass();
System.out.println(c1 == c2); 

在继续往下看之前,先想一想,这道题输出的结果是什么?

是 true 还是 false ?

这道题输出的结果是 true。因为无论对于 ArrayList 还是 ArrayList,它们的 Class 类型都是一直的,都是 ArrayList.class。

那它们声明时指定的 String 和 Integer 到底体现在哪里呢?

答案是体现在类编译的时候。

当 JVM 进行类编译时,会进行泛型检查,如果一个集合被声明为 String 类型,那么它往该集合存取数据的时候就会对数据进行判断,从而避免存入或取出错误的数据。

也就是说:泛型只存在于编译阶段,而不存在于运行阶段。在编译后的 class 文件中,是没有泛型这个概念的。

上面我们只是说了泛型在集合中的使用方式,但其实泛型的应用范围不仅仅只是集合,还包括类、方法、Map 接口等等。

泛型的应用还广泛存在于下面几种情形:泛型类、泛型方法、泛型集合。

泛型类

泛型类一般使用字母 T 作为泛型的标志。

public class GenericClass<T> {
    private T object;
    public T getObject() {
        return object;
    }
    public void setObject(T object) {
        this.object = object;
    }
}

使用:

public static void main(String[] args) {
    GenericClass<Integer> integerGenericClass = new GenericClass<>(100);
    integerGenericClass.showType();
    GenericClass<String> stringGenericClass = new GenericClass<>("www.cnblogs.com/chanshuyi");
    stringGenericClass.showType();
}

泛型方法

泛型方法一般使用字母 T 作为泛型的标志。

public class GenericMethod {
    public static <T> T getObject(Class<T> clz) throws InstantiationException, IllegalAccessException{
        T t = clz.newInstance();
        return t;
    }
}

使用:

public static void main(String[] args) throws Exception{
    GenericMethod genericMethod = getObject(GenericMethod.class);
    System.out.println("Class:" + genericMethod.getClass().getName());
}

泛型集合

除了使用 T 作为泛型类的标志之外,在需要使用 Map 的类中,通常使用 K V 两个字母表示 Key Value 对应的类型。

public class GenericMap<K, V> {
    private K key;
    private V value;
    public void put(K key, V value) {
        this.key = key;
        this.value = value;
    }
}

使用:

public static void main(String[] args) {
        GenericMap<Integer, String> team = new GenericMap<>();
        team.put(1, "YaoMin");
        team.put(2, "Me");
        GenericMap<String, Integer> score = new GenericMap<>();
        score.put("YaoMin", 88);
        score.put("Me", 80);
    }

总结

我们通过一个简单的例子理解了泛型诞生的缘由,之后又通过一个常见的面试题明白了泛型只存在于编译期间的本质,最后介绍了常见的泛型使用场景。

下篇文章,我们将介绍泛型中通配符的使用。

文章首发于【博客园-陈树义】,点击跳转到原文《大白话说Java泛型(一):入门、原理、使用》

编辑:帝道

发布:2019-04-22 00:00:00

当前文章:http://adsl66.com/content/2019-02/04/content_76277.html

省购省的钱在哪里 QQ浏览器怎么赚钱 注册手机卡赚佣金吗, 本想素股 优益刷单是真的吗 微信零钱可以赚收益 好省赚钱是真的吗 怎么加入微信投票赚钱

55299 81381 64073 63983 47397 8764456221 98073 36310

我要说两句: (0人参与)

发布