java泛型的实现原理_共享手册|想学Java吗?那先来看看JAVA泛型实现原理

【摘要】作为一门面向对象编程语言,Java吸收了C++语言的优点,也展现了其强大的一面,我们能在各个地方看到其功能强大和简单易用的两个特征,当然,也吸引了很多程序员的注意力,所以就有人想了解Java的相关内容,今天就来讲讲JAVA泛型实现原理的相关内容。

1、JAVA泛型实现原理——Java范型时编译时

Java范型时编译时技术,在运行时不包含范型信息,仅仅Class的实例中包含了类型参数的定义信息。

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

T badCast(T t, Object o) {

return (T) o; // unchecked warning

}

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

着你不能依靠他们进行类型转换。

2、JAVA泛型实现原理——一个泛型类被其所有调用共享

下面的代码打印的结果是什么?

List l1 = new ArrayList();

List l2 = new ArrayList();

System.out.println(l1.getClass() == l2.getClass());

或许你会说false,但是你想错了。它打印出true。因为一个泛型类的所有实例在运行时具有相同的运行时类(class),

而不管他们的实际类型参数。

事实上,泛型之所以叫泛型,就是因为它对所有其可能的类型参数,有同样的行为;同样的类可以被当作许多不同

的类型。作为一个结果,类的静态变量和方法也在所有的实例间共享。这就是为什么在静态方法或静态初始化代码

中或者在静态变量的声明和初始化时使用类型参数(类型参数是属于具体实例的)是不合法的原因。

3、JAVA泛型实现原理——转型和instanceof

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

Collection cs = new ArrayList();

if (cs instanceof Collection) { ...} // 非法

类似的,如下的类型转换

Collection cstr = (Collection) cs;

得到一个unchecked warning,因为运行时环境不会为你作这样的检查。

4、JAVA泛型实现原理——Class的范型处理

Java 5之后,Class变成范型化了。

JDK1.5中一个变化是类 java.lang.Class是泛型化的。这是把泛型扩展到容器类之外的一个很有意思的例子。

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

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

的对象集合(collection)。

一个方法是显式的传递一个工厂对象,像下面的代码:

interface Factory {

public T[] make();

}

public Collection select(Factory factory, String statement) {

Collection result = new ArrayList();

/* 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(){

public EmpInfo make() {

return new EmpInfo();

}

} , ”selection string”);

也可以声明一个类 EmpInfoFactory 来支持接口 Factory:

class EmpInfoFactory implements Factory { ...

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 emps=sqlUtility.select(EmpInfo.class, ”select * from emps”); ...

public static Collection select(Classc, String sqlStatement) {

Collection result = new ArrayList();

/* 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、JAVA泛型实现原理——保证代码的兼容性

为了保证代码的兼容性,下面的代码编译器(javac)允许,类型安全有你自己保证

List l = new ArrayList();

List l = new ArrayList();

6、JAVA泛型实现原理——在将你的类库升级为范型版本时,慎用协变式返回值。

例如,将代码

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的学习之路顺利。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值