`
cantellow
  • 浏览: 847238 次
  • 性别: Icon_minigender_1
  • 来自: 草帽海贼团
社区版块
存档分类
最新评论

泛型のwhy&how

    博客分类:
  • Java
 
阅读更多

 

Why,Java为什么需要泛型?

如果我需要我的代码适用于多种类型,那么我可以使用object;如果我需要限定这个类型必须具有特定的约定,那么我可以定义接口或者抽象类。总之,我都可以解决,再加上Java的反射功能,没有泛型之前Collection库一样过得好好的。

 

那么java为什么还要加上泛型这样的语法糖呢?答案就是,在编译期间就检查类型转换是否正确,而不是拖延到运行时期。我想这也是Java泛型最吸引人的地方,它无法像C++模板那样强大,但也不是一无是处。

 

在泛型没有出现之前,容器里的实现都是通过超类object可以让任何对象都放进去,但是一旦放进去之后,特定类型就向上转型为object,从而丧失了类型信息。要想从里面得到特定的类型信息只有手动强制转换,但是这个转换在编译时期是无法预知的,运行时期完全有可能抛出ClassCastException异常。从软件工程的角度看,如果能在编译时期就检查类型转换十分正确,这是一种进步。

什么时候使用泛型?

如果你要编写可以应用于多种类型的代码(比如你重新定义一种数据结构,或者一种算法),你的头脑的第一反应是使用object,但是考虑前面所说的,你可以使用没有边界的泛型来代替。如果你的代码必须现定于使用某种接口或类的子类,那么可以考虑使用有边界的泛型来代替。

举例,java.lang.ThreadLocal的实现

ThreadLocal是用来为每一个线程提供一个副本,可以确保这个副本变量只在一个线程中被使用到。



 典型的用法是保持数据库连接connection的线程封闭性:

 

private static ThreadLocal<Connection> connectionHolder
    = new ThreadLocal<Connection>() {
        public Connection initialValue() {
            return DriverManager.getConnection(DB_URL);
        }
    };

public static Connection getConnection() {
    return connectionHolder.get();
}

ThreadLocal的实现也是采用了泛型,源代码中get方法返回的是T,基于擦除的认识,在运行时,这个T实际上看不到了,也不是真正的Connection,而是普通的object,你完全可以将上面的代码<Connection>忽略掉,把ThreadLocal源代码里的T看成object,那你可能要问,它的get方法为什么就知道返回的是Connection类型呢,原因是编译器编译后,在get方法自动加上了类型转换并添加了桥方法,能做到这一步的前提是在编译时期已经经过了类型检查,如果类型检查不通过就不会生成class文件,也就不会有后面这些步骤了。

How,擦除,一种折中方案

泛型其实算不上是一种语言特性,它只是java实现泛型技术的一种折中,至于为什么选择擦除,我猜可能是为了保持向后兼容,使得泛型代码和非泛型代码能够共存。为了保持向后兼容,泛型对JVM是不可见的,也就是JVM根本不需要做很多变化,因为既然你实现泛型的主要目标是提供编译时期的类型检查安全,那么很多工作都应该在编译时期做,实际上也是这样的,擦除也就是这么一个原理,在运行时期看不见任何泛型参数,JVM执行泛型代码就像执行以前的普通代码一样!(当然不做任何改变也是不可能的,可以参考http://icyfenix.iteye.com/blog/1021949)。

 

我觉得理解擦除原理最重要的是区分编译时期和运行时期:

擦除步骤

首先,编译器检查类型是否安全,就像下面的代码是通不过的:

 

List<String > list = new ArraryList<String>();
list.add(“cantellow”);
int integer = list.get(0);//compile error

 

然后,将参数化类型中的类型参数"擦除"erasure)掉,并且将类型变量用"上限(upper bound"取代,通常情况下这些上限是 Object。这里的类型变量是指实例域,本地方法域,方法参数以及方法返回值中用来标记类型信息的"变量",例如:实例域中的变量声明 A elem;,方法声明 Node (A elem){};,其中,A 用来标记 elem 的类型,它就是类型变量。

 

擦除规则:

如果泛型类型的类型变量没有限定(既是<T>) ,那么我们就用Object作为原始类型;

如果有限定(<T extends XClass>),我们就XClass作为原始类型;

如果有多个限定(<T extends XClass1&XClass2>),我们就用第一个边界的类型变量XClass1类作为原始类型; 

 

最后,添加类型转换并插入"桥方法"bridge method),以便覆盖(overridden)可以正常的工作。关于更详细的擦除步骤请参考:http://www.iteye.com/topic/549509

  • 大小: 30.9 KB
2
1
分享到:
评论

相关推荐

    关于C#泛型列表List&lt;T&gt;的基本用法总结

    在C#编程中,泛型列表`List&lt;T&gt;`是一个常用的数据结构,它允许存储类型统一的元素集合。本文将深入探讨`List&lt;T&gt;`的基本用法,帮助开发者更好地理解和使用这一功能。 1. **创建和初始化** - `List&lt;T&gt;`可以通过无参...

    什么是泛型编程&STL

    泛型编程是C++编程中的一种重要理念,它允许开发者编写独立于具体数据类型的代码,以提高代码的重用性和效率。泛型编程的核心在于模板(templates),它使得程序员能够创建能够处理不同类型数据的函数和类。这样,同...

    C#泛型类、泛型方法、泛型接口、泛型委托的实例

    本文将深入探讨泛型类、泛型方法、泛型接口和泛型委托,并通过实例来阐述它们的应用。 首先,我们来看泛型类。泛型类是具有一个或多个类型参数的类。类型参数是在定义类时使用的占位符,实际的类型在创建类的实例时...

    泛型dao 泛型dao 泛型dao

    Struts2、Hibernate、Spring整合的泛型DAO (本人评价: 代码开发效率提高30% 代码出错率减少70%) 对于大多数开发人员,系统中的每个 DAO 编写几乎相同的代码到目前为止已经成为一种习惯。虽然所有人都将这种重复...

    泛型&通配符常见面试题总结

    泛型和通配符是Java编程中的重要概念,它们在处理类型安全和代码复用方面起着关键作用。本文将深入探讨这两个主题,并提供一些常见的面试题,帮助开发者理解和掌握这些知识点。 首先,我们来理解泛型。泛型是Java 5...

    【Flutter】Dart 泛型 ( 泛型类 泛型方法 特定类型约束的泛型 ).zip

    【Flutter】Dart 泛型 ( 泛型类 | 泛型方法 | 特定类型约束的泛型 ) https://hanshuliang.blog.csdn.net/article/details/114059611 博客源码快照

    泛型学习和泛型接口和泛型经典示例

    泛型学习和泛型接口和泛型经典示例

    JAVA-泛型课件-泛型课件

    泛型是Java语言的一个重要特性,首次出现在Java SE 1.5版本中。它的引入主要是为了解决在集合操作中类型安全性的问题,并通过引入参数化类型的概念,提高了代码的复用性与可读性。 ### 泛型概念 泛型,即参数化...

    泛型java的泛型知识,非常有用

    Java 泛型是一种强大的语言特性,自JDK 5.0引入以来,极大地提升了代码的类型安全性以及重用性。泛型允许我们在类、接口和方法中使用类型参数,这样在编译时期就能检查类型匹配,减少运行时类型转换异常。 1. **...

    关于java基础的泛型的练习

    Java泛型是Java SE 5.0引入的一个重要特性,它极大地增强了代码的类型安全性和可读性。泛型在编程中的应用广泛,特别是在集合框架中,使得我们可以在编译时就检查类型,避免了不必要的类型转换,并且提高了代码的...

    java泛型指南 经典

    ### Java泛型指南经典知识点解析 #### 一、引言 Java 1.5 版本引入了一系列重要的语言特性,其中“泛型”是其中一项关键特性。泛型的引入极大地提高了 Java 语言的类型安全性和代码重用性。本文档旨在深入探讨 ...

    VC++ 2005:泛型编程

    【VC++ 2005:泛型编程】 泛型编程是C++/CLI中的一种重要特性,允许程序员创建可重用的代码,这些代码能够处理多种数据类型,而无需每次都复制和修改代码。泛型编程的核心思想是参数化类型,即将数据类型作为一个...

    SSH泛型代码实例

    SSH泛型代码实例是关于Java编程中的一种常见技术——Spring、Struts和Hibernate(SSH)框架结合使用泛型的应用示例。泛型是Java SE 5.0引入的一个重要特性,它允许在编译时检查类型安全,并且所有的强制转换都是自动...

    java 1.5泛型详解

    Java泛型是自Java 1.5版本引入的一项重要特性,极大地提高了代码的类型安全性和重用性。本文将深入探讨Java泛型的概念、优点、使用方式及其在实际开发中的应用。 **一、泛型的基本概念** 泛型是Java语言中的一种...

    泛型笔记学习2009

    ### 泛型基础知识与应用详解 #### 泛型概述 泛型是Java语言的一个重要特性,它主要解决了在集合框架中频繁出现的类型转换问题,同时也增强了类型安全性。泛型的概念最早出现在Java 5.0版本中,它允许开发者创建能够...

    c#泛型类、泛型方法、泛型接口、泛型委托

    泛型主要分为四个关键部分:泛型类、泛型方法、泛型接口和泛型委托。下面将详细介绍这四个方面。 1. 泛型类: 泛型类是具有一个或多个类型参数的类。这些类型参数是占位符,代表一种未知的数据类型,直到在创建类...

    C#泛型,非泛型实现枚举

    在C#编程中,泛型和枚举是两种非常重要的概念。泛型提供了一种方式,使得代码可以处理多种数据类型,而无需为每种类型重复编写相同逻辑。枚举则是用于定义一组预定义的常量,便于表示一组相关的值。下面我们将详细...

    C#泛型集合与非泛型集合

    ### C# 泛型集合与非泛型集合详解 #### 一、概述 在.NET Framework Class Library (FCL) 中,提供了丰富的集合类型,这些集合类型是编程中不可或缺的工具。根据是否支持泛型特性,这些集合大致可以分为两类:泛型...

Global site tag (gtag.js) - Google Analytics