Java的Generic Programming简介_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > Java的Generic Programming简介

Java的Generic Programming简介

 2013/9/7 21:11:53  notesth  程序员俱乐部  我要评论(0)
  • 摘要:下面是自己学习Java的genericprogramming后的一点总结,以供大家尽快地对其有一个大概的了解。文章的思路是:1.定义;2.原理;3.通配符(wildcardtypes)。1.定义什么是genericprogramming?在定义class,interface和method的时候,generics可以把class或者是interface当成一个类型参数。参考的是http://docs.oracle.com/javase/tutorial/java/generics/why
  • 标签:简介 Java
下面是自己学习Java的generic programming后的一点总结,以供大家尽快地对其有一个大概的了解。

文章的思路是:1. 定义;2. 原理;3. 通配符(wildcard types)

1. 定义

什么是generic programming?在定义class,interface和method的时候,generics可以把class或者是interface当成一个类型参数。参考的是http://docs.oracle.com/javase/tutorial/java/generics/why.html

首先看怎么定义一个generic class,举个代码例子,这样更直观一点。



public class Pair<T>
{
	public Pair() { first = null; second = null; }
	public Pair(T first, T second) { this.first = first; this.second = second; }
	public T getFirst() { return first; }
	public T getSecond() { return second; }
	public void setFirst(T newValue) { first = newValue; }
	public void setSecond(T newValue) { second = newValue; }
	private T first;
	private T second;
	
	public static void main(String[] args){
		Pair<Integer> integerPair = new Pair(0, 1);
		Pair<String> stringPair = new Pair("thinking in java", "java core");
		...
	}
}



然后看下怎么定义generic method,还是看代码。

class ArrayAlg
{
public static  T getMiddle(T[] a)
{
return a[a.length / 2];
}
}



到此,定义类和方法的具体写法就介绍完了,下面也很容易想到对于参数类型“T”有没有什么限制呢?下面就介绍“T”的使用限制范围(Bounds of Type Variable)。

可以定义代码:

public static <T extends Comparable>  Pair minmax(T[] a)...



其中Comparable就是T的bounding type,实际就是T的一个继承关系中的限制条件了。注意,这个概念很重要,在之后介绍generics在虚拟机中怎么运行的时候会提及。

2. 原理

也就是介绍generics在虚拟机中是什么样的。

在虚拟机中,所有的类或者是接口都必须有一个类型,那“T”的类型是什么呢?答案自然不是“T”,而是在定义了generic type之后,虚拟机会自动提供一个raw type。

那什么又是raw type?他不是一个具体的类或者是接口,而是定义generics的所有的T的bounding type的总称,按语法来讲,他不是个名词,而是个代词。

比如最开始的例子,Pair<T>,其的raw type就是Object,而...<T extends Comparable>...的raw type就是Comparable。

在虚拟机中,第一个Pair<T>例子的代码就会变成:

public class Pair
{
public Pair(Object first, Object second)
{
this.first = first;
this.second = second;
}
public Object getFirst() { return first; }
public Object getSecond() { return second; }
public void setFirst(Object newValue) { first = newValue; }
public void setSecond(Object newValue) { second = newValue; }
private Object first;
private Object second;

...
}


那经过转化之后,“T”已经不是原来的那个“T”了,但是为什么Pair<Integer>(当然Pair<String>同理)还是原来的Pair<Integer>呢?

因为编译器会在把值取出来之前再强制转化类型。

即,generics在虚拟机里的过程是:

  • 存,存成bounding type类型的
  • 取,把bounding type类型的东西再还原回来


这个过程非常重要,很多地方都是拿这个过程解释的,当然,也有一部分冲突是由此引起的。

下面就介绍一个由于此过程引起的冲突以及由此引出的一个概念,bridge method。

看如下代码,注意这段代码是合法的:

class DateInterval extends Pair<Date>
{
public void setSecond(Date second)
{
if (second.compareTo(getFirst()) >= 0)
super.setSecond(second);
}
. . .
}


因为DateInterval是继承Pair<Date>,自然继承了Pair<Date>的setSecond方法,但是由于在虚拟机中Pair<Date>的setSecond方法被存为

public void setSecond(Object second)
{
...
}


即相当于在DateInterval中有两个名字相同,参数不同(但是注意参数有继承关系)的方法,如果要调用setSecond就不知所措了,下图阴影部分为继承Pair<Date>所得,仅为示例之用。


这时候编译器会提供一个bridge method,来解决两个方法冲突的问题。

public void setSecond(Object second) { setSecond((Date) second); }


这样问题就得到解决了,注意,这里是编译器的事儿,与写代码无关。

在原理部分需要注意的几点是
  • 实际上是没有generics存在的,也就是上面的“T”
  • 所有的type parameters都会换成他们的bounding type
  • bridge method会解决冲突的问题
  • 在虚拟机里面会执行类型转换以确保安全


3. 通配符(wildcard types)

也就是在使用generics的时候嫌麻烦,可以使得generic type中的type parameter可以在继承关系上使用更灵活点,或者是可以使用type parameter的父类,或者是可以使用其的子类。

比如在方法:

public static void printBuddies(Pair<Employee> p)
{
Employee first = p.getFirst();
Employee second = p.getSecond();
System.out.println(first.getName() + " and " + second.getName() + " are buddies.";
}


其中要想给printBuddies传递一个Pair<Manager>类型的参数是不合法的,于是乎产生了一种新的定义方法:

public static void printBuddies(Pair<? extends Employee> p)


这样,就可以把Pair<Manager>类型的参数传入方法了。同理还可以定义代码:

public static void printBuddies(Pair<? super Manager> p)


这样的意思就变成所有Manager的父类都可以调用此段代码了。

最后也可以就通配符“?”一个,什么继承关系都没有,比如:

public static void printBuddies(Pair<?> p)


具体通配符的用法可以参考http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html。

没有介绍的太详细,但求大概能对generics有一个整体印象。

参考资料
  • http://docs.oracle.com/javase/tutorial/extra/generics/index.html
  • Core.Java.Volume.I.Fundamentals,8th.Edition
  • 描述: DateInterval
  • 大小: 9.4 KB
  • 查看图片附件
发表评论
用户名: 匿名