1. Java范型时编译时技术,在运行时不包含范型信息,仅仅Class的实例中包含了类型参数的定义信息。
泛型是通过java编译器的称为擦除(erasure)的前端处理来实现的。你可以(基本上就是)把它认为是一个从源码到源码的转换,它把泛型版本转换成非泛型版本。 基本上,擦除去掉了所有的泛型类型信息。所有在尖括号之间的类型信息都被扔掉了,因此,比如说一个List<String>类型被转换为List。所有对类型变量的引用被替换成类型变量的上限(通常是Object)。而且,无论何时结果代码类型不正确,会插入一个到合适类型的转换。

   <T> T badCast(T t, Object o) {
return (T) o; // unchecked warning
}

类型参数在运行时并不存在。这意味着它们不会添加任何的时间或者空间上的负担,这很好。不幸的是,这也意味
着你不能依靠他们进行类型转换。

2.一个泛型类被其所有调用共享
下面的代码打印的结果是什么?

   List<String> l1 = new ArrayList<String>();
List<Integer> l2 = new ArrayList<Integer>();
System.out.println(l1.getClass() == l2.getClass());

或许你会说false,但是你想错了。它打印出true。因为一个泛型类的所有实例在运行时具有相同的运行时类(class),
而不管他们的实际类型参数。
事实上,泛型之所以叫泛型,就是因为它对所有其可能的类型参数,有同样的行为;同样的类可以被当作许多不同
的类型。作为一个结果,类的静态变量和方法也在所有的实例间共享。这就是为什么在静态方法或静态初始化代码
中或者在静态变量的声明和初始化时使用类型参数(类型参数是属于具体实例的)是不合法的原因。

3. 转型和instanceof
泛型类被所有其实例(instances)共享的另一个暗示是检查一个实例是不是一个特定类型的泛型类是没有意义的。

   Collection cs = new ArrayList<String>();
if (cs instanceof Collection<String>) { ...} // 非法

类似的,如下的类型转换
Collection<String> cstr = (Collection<String>) cs;
得到一个unchecked warning,因为运行时环境不会为你作这样的检查。

4. Class的范型处理
Java 5之后,Class变成范型化了。
JDK1.5中一个变化是类 java.lang.Class是泛型化的。这是把泛型扩展到容器类之外的一个很有意思的例子。

现在,Class有一个类型参数T, 你很可能会问,T 代表什么?它代表Class对象代表的类型。比如说,String.class类型代表 Class<String>,Serializable.class代表 Class<Serializable>。这可以被用来提高你的反射代码的类型安全。

特别的,因为 Class的 newInstance() 方法现在返回一个T, 你可以在使用反射创建对象时得到更精确的类型。比如说,假定你要写一个工具方法来进行一个数据库查询,给定一个SQL语句,并返回一个数据库中符合查询条件
的对象集合(collection)。

一个方法是显式的传递一个工厂对象,像下面的代码:
interface Factory<T> {

public T[] make();

}
public <T> Collection<T> select(Factory<T> factory, String statement) {

    Collection<T> result = new ArrayList<T>();
/* run sql query using jdbc */
for ( int i=0; i<10; i++ ) { /* iterate over jdbc results */
T item = factory.make();
/* use reflection and set all of item’s fields from sql results */
result.add( item );
}
return result;

}
你可以这样调用:
select(new Factory<EmpInfo>(){

 public EmpInfo make() {
return new EmpInfo();
}
} , ”selection string”);

也可以声明一个类 EmpInfoFactory 来支持接口 Factory:
class EmpInfoFactory implements Factory<EmpInfo> { ...

public EmpInfo make() { return new EmpInfo();}

}
然后调用:
select(getMyEmpInfoFactory(), "selection string");
这个解决方案的缺点是它需要下面的二者之一:
调用处那冗长的匿名工厂类,或为每个要使用的类型声明一个工厂类并传递其对象给调用的地方这很不自然。

使用class类型参数值是非常自然的,它可以被反射使用。没有泛型的代码可能是:
Collection emps = sqlUtility.select(EmpInfo.class, ”select * from emps”); ...
public static Collection select(Class c, String sqlStatement) {

 Collection result = new ArrayList();
/* run sql query using jdbc */
for ( /* iterate over jdbc results */ ) {
Object item = c.newInstance();
/* use reflection and set all of item’s fields from sql results */
result.add(item);
}
return result;

}
但是这不能给我们返回一个我们要的精确类型的集合。现在Class是泛型的,我们可以写:
Collection<EmpInfo> emps=sqlUtility.select(EmpInfo.class, ”select * from emps”); ...
public static <T> Collection<T> select(Class<T>c, String sqlStatement) {

 Collection<T> result = new ArrayList<T>();
/* run sql query using jdbc */
for ( /* iterate over jdbc results */ ) {
T item = c.newInstance();
/* use reflection and set all of item’s fields from sql results */
result.add(item);
}
return result;

}
来通过一种类型安全的方式得到我们要的集合。
这项技术是一个非常有用的技巧,它已成为一个在处理注释(annotations)的新API中被广泛使用的习惯用法。

5. 为了保证代码的兼容性,下面的代码编译器(javac)允许,类型安全有你自己保证
List l = new ArrayList<String>();
List<String> l = new ArrayList();

6. 在将你的类库升级为范型版本时,慎用协变式返回值。
例如,将代码
public class Foo {

 public Foo create(){
return new Foo();
}

}

public class Bar extends Foo {

 public Foo create(){
return new Bar();
}

}
采用协变式返回值风格,将Bar修改为
public class Bar extends Foo {

 public Bar create(){
return new Bar();
}

}
要小心你类库的客户端。
上海尚学堂java培训原作,请多关注。陆续java相关技术文章奉上!

JAVA泛型实现原理的更多相关文章

  1. Java泛型-内部原理: 类型擦除以及类型擦除带来的问题

    一:Java泛型的实现方法:类型擦除 大家都知道,Java的泛型是伪泛型,这是因为Java在编译期间,所有的泛型信息都会被擦掉,正确理解泛型概念的首要前提是理解类型擦除.Java的泛型基本上都是在编译 ...

  2. 关于Java泛型实现原理的思考与一般用法示例总结

    面向对象的一个重要目标是对代码重用的支持.支持这个目标的一个重要机制就是泛型机制.在1.5版本之前,java并没有直接支持泛型实现,泛型编程的实现时通过使用继承的一些基本概念来完成的. 这种方式的局限 ...

  3. java 泛型实现原理

    泛型思想最早在C++语言的模板(Templates)中产生,Java后来也借用了这种思想.虽然思想一致,但是他们存在着本质性的不同. C++中的模板是真正意义上的泛型,在编译时就将不同模板类型参数编译 ...

  4. java泛型学习(2)

    一:深入泛型使用.主要是父类和子类存在泛型的demo /** * 父类为泛型类 * @author 尚晓飞 * @date 2014-7-15 下午7:31:25 * * * 父类和子类的泛型. * ...

  5. Java泛型总结---基本用法,类型限定,通配符,类型擦除

    一.基本概念和用法 在Java语言处于还没有出现泛型的版本时,只能通过Object是所有类型的父类和类型强制转换两个特点的配合来实现类型泛化.例如在哈希表的存取中,JDK1.5之前使用HashMap的 ...

  6. 浅析Java泛型

    什么是泛型? 泛型是JDK 1.5的一项新特性,它的本质是参数化类型(Parameterized Type)的应用,也就是说所操作的数据类型被指定为一个参数,在用到的时候在指定具体的类型.这种参数类型 ...

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

    文章首发于[博客园-陈树义],点击跳转到原文<大白话说Java泛型(一):入门.原理.使用> 远在 JDK 1.4 版本的时候,那时候是没有泛型的概念的.当时 Java 程序员们写集合类的 ...

  8. java泛型的作用及实现原理

    一.泛型的介绍 泛型是Java 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数.这种参数类型可以用在类.接口和方法的创建中,分别称为泛型类.泛型接口.泛型方法. Ja ...

  9. 大白话说Java泛型:入门、使用、原理

    文章首发于[博客园-陈树义],点击跳转到原文<大白话说Java泛型:入门.使用.原理> 远在 JDK 1.4 版本的时候,那时候是没有泛型的概念的.当时 Java 程序员们写集合类的代码都 ...

随机推荐

  1. MVC开发T4代码生成之一----文本模板基础

    T4文本模板 T4全写为Text Template Transformation Toolkit,是一种编程辅助工具,用来使程序代码自(懒)动(猿)生(福)成(利)的工具.MVC开发中大量使用了T4模 ...

  2. /lib/lsb/init-functions

    lsb_functions="/lib/lsb/init-functions" if test -f $lsb_functions ; then . $lsb_functions

  3. core的微服务相关

    网关是ocelot consul 服务发现 配置中心apollo

  4. windows2012 raid架构 忘记系统管理员密码的解决方法

    1. http://bbs.51cto.com/thread-939710-1.html 2. https://wenku.baidu.com/view/115783cd0b4e767f5acfcef ...

  5. beamer插入图片的一些技巧

    1. 点一下,让另一张隐藏的图出现

  6. Windows和Frames之间的切换

    一些web应用程序有许多Frames或多个Windows. WebDriver支持使用“switchTo”的方法实现的窗口之间切换. driver.switchTo().window("wi ...

  7. 解决Ubuntu 16.04 上Android Studio2.3上面运行APP时提示DELETE_FAILED_INTERNAL_ERROR Error while Installing APKs的问题

    本人工作环境:Ubuntu 16.04 LTS + Android Studio 2.3 AVD启动之后,运行APP,报错提示: DELETE_FAILED_INTERNAL_ERROR Error ...

  8. CSS绝对定位的原点:是在border上、padding上还是在content上?

    用了那么久的绝对定位,却一直没在意一个问题,就是绝对定位的原点,究竟是在盒模型的哪一处.今天想到这个问题,直接搜索没有找到标准文档,也没有搜索到相关的问题,于是决定自己动手实现一下看看,并把这个结果发 ...

  9. Leetcode——Two Sum(easy)

    题目:Given nums = [2, 7, 11, 15], target = 9, Because nums[0] + nums[1] = 2 + 7 = 9, return [0, 1] 代码: ...

  10. 第三次scrum作业

    一.第三次冲刺任务 ! 在已有的基础上实现图书馆管理员对图书信息的查询以及对图书借阅情况的查询. 二.用户故事 本次的用户是图书馆的管理员 用户输入对应的管理员的账号和密码 用户选择图书查询,进入图书 ...