<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Information Retrieval Blog &#187; 泛型</title>
	<atom:link href="http://blog.zye.me/tag/%e6%b3%9b%e5%9e%8b/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.zye.me</link>
	<description>REAL TIME DATA PROCESSING, DISTRIBUTED COMPUTING, PATTERN DISCOVERY</description>
	<lastBuildDate>Tue, 31 Jan 2012 02:05:19 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Java1.5泛型指南中文版(Java1.5 Generic Tutorial, zhuan)</title>
		<link>http://blog.zye.me/2011/05/11788.html</link>
		<comments>http://blog.zye.me/2011/05/11788.html#comments</comments>
		<pubDate>Fri, 20 May 2011 02:27:33 +0000</pubDate>
		<dc:creator>yezheng</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[中文版]]></category>
		<category><![CDATA[信息检索]]></category>
		<category><![CDATA[泛型]]></category>

		<guid isPermaLink="false">http://www.5yiso.cn/2008/02/11788.html</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[]]></content:encoded>
			<wfw:commentRss>http://blog.zye.me/2011/05/11788.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Java泛型中通配符使用</title>
		<link>http://blog.zye.me/2010/02/50190.html</link>
		<comments>http://blog.zye.me/2010/02/50190.html#comments</comments>
		<pubDate>Fri, 19 Feb 2010 16:10:26 +0000</pubDate>
		<dc:creator>yezheng</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[泛型]]></category>
		<category><![CDATA[通配符]]></category>

		<guid isPermaLink="false">http://blog.so8848.com/?p=50190</guid>
		<description><![CDATA[泛型是一种表示类或方法行为对于未知类型的类型约束的方法，比如 “不管这个方法的参数 x 和 y 是哪种类型，它们必须是相同的类型”，“必须为这些方法提供同一类型的参数” 或者 “foo() 的返回值和bar() 的参数是同一类型的”。虽然 String 是 Object 的子类，但是 List&#60;String&#62; 和 List&#60;Object&#62; 之间并没有什么关系——List&#60;String&#62; 不是 List&#60;Object&#62; 的子类或者子类型。 Wildcards Consider the problem of writing a routine that prints out all the elements in a collection. Here&#8217;s how you might write it in an older version of the language (i.e., a pre-5.0 release): void printCollection(Collection <a href='http://blog.zye.me/2010/02/50190.html'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p><span class="Apple-style-span" style="font-family: verdana; font-size: 12px; line-height: 19px;">泛型是一种表示类或方法行为对于未知类型的类型约束的方法，比如 “不管这个方法的参数 <code>x</code> 和 <code>y</code> 是哪种类型，它们必须是相同的类型”，“必须为这些方法提供同一类型的参数” 或者 “<code>foo()</code> 的返回值和<code>bar()</code> 的参数是同一类型的”。</span><span class="Apple-style-span" style="font-family: verdana; font-size: 14px; line-height: 22px;"><span style="font-family: 宋体;">虽然</span> <span style="font-family: 'Courier New';" lang="EN-US">String</span><span lang="EN-US"> </span><span style="font-family: 宋体;">是</span> <span style="font-family: 'Courier New';" lang="EN-US">Object</span><span lang="EN-US"> </span><span style="font-family: 宋体;">的子类，但是</span><span style="font-family: 'Courier New';" lang="EN-US"> List&lt;String&gt;</span><span lang="EN-US"> </span><span style="font-family: 宋体;">和</span> <span style="font-family: 'Courier New';" lang="EN-US">List&lt;Object&gt;</span><span lang="EN-US"> </span><span style="font-family: 宋体;">之间并没有什么关系——</span><span style="font-family: 'Courier New';" lang="EN-US">List&lt;String&gt;</span><span lang="EN-US"> </span><span style="font-family: 宋体;">不是</span> <span style="font-family: 'Courier New';" lang="EN-US">List&lt;Object&gt;</span><span lang="EN-US"> </span><span style="font-family: 宋体;">的子类或者子类型。</span></span></p>
<p><span class="Apple-style-span" style="color: #e76f00; font-family: '-webkit-sans-serif'; font-size: 20px; font-weight: bold; line-height: normal;">Wildcards</span></p>
<blockquote><p>Consider the problem of writing a routine that prints out all the elements in a collection. Here&#8217;s how you might write it in an older version of the language (i.e., a pre-5.0 release):</p>
<blockquote>
<pre><strong>void</strong> printCollection(Collection c) {     Iterator i = c.iterator();     <strong>for</strong> (k = 0; k &lt; c.size(); k++) {         System.out.println(i.next());     } }</pre>
</blockquote>
<p>And here is a naive attempt at writing it using generics (and the new <code>for</code> loop syntax):</p>
<blockquote>
<pre><strong>void</strong> printCollection(Collection&lt;Object&gt; c) {     <strong>for</strong> (Object e : c) {         System.out.println(e);     } }</pre>
</blockquote>
<p>The problem is that this new version is much less useful than the old one. Whereas the old code could be called with any kind of collection as a parameter, the new code only takes <code>Collection&lt;Object&gt;</code>, which, as we&#8217;ve just demonstrated, is <strong>not</strong> a supertype of all kinds of collections!So what <strong>is</strong> the supertype of all kinds of collections? It&#8217;s written <code>Collection&lt;?&gt;</code> (pronounced &#8220;collection of unknown&#8221;), that is, a collection whose element type matches anything. It&#8217;s called a <strong>wildcard type</strong> for obvious reasons. We can write:</p>
<blockquote>
<pre><strong>void</strong> printCollection(Collection&lt;?&gt; c) {     <strong>for</strong> (Object e : c) {         System.out.println(e);     } }</pre>
</blockquote>
<p>and now, we can call it with any type of collection. Notice that inside <code>printCollection()</code>, we can still read elements from <code>c</code> and give them type <code>Object</code>. This is always safe, since whatever the actual type of the collection, it does contain objects. It isn&#8217;t safe to add arbitrary objects to it however:</p>
<blockquote>
<pre>Collection&lt;?&gt; c = new ArrayList&lt;String&gt;(); c.add(new Object()); // Compile time error</pre>
</blockquote>
<p>Since we don&#8217;t know what the element type of <code>c</code> stands for, we cannot add objects to it. The <code>add()</code> method takes arguments of type <code>E</code>, the element type of the collection. When the actual type parameter is <code>?</code>, it stands for some unknown type. Any parameter we pass to <code>add</code> would have to be a subtype of this unknown type. Since we don&#8217;t know what type that is, we cannot pass anything in. The sole exception is <code>null</code>, which is a member of every type.On the other hand, given a <code>List&lt;?&gt;</code>, we <strong>can</strong> call <code>get()</code> and make use of the result. The result type is an unknown type, but we always know that it is an object. It is therefore safe to assign the result of <code>get()</code> to a variable of type <code>Object</code> or pass it as a parameter where the type <code>Object</code> is expected.</p>
<h4 style="color: #e76f00; font-family: sans-serif;">Bounded Wildcards</h4>
<p>Consider a simple drawing application that can draw shapes such as rectangles and circles. To represent these shapes within the program, you could define a class hierarchy such as this:</p>
<blockquote>
<pre><strong>public abstract class</strong> Shape {     <strong>public abstract void</strong> draw(Canvas c); }  <strong>public class</strong> Circle <strong>extends</strong> Shape {     <strong>private int</strong> x, y, radius;     <strong>public void</strong> draw(Canvas c) {         ...     } }  <strong>public class</strong> Rectangle <strong>extends</strong> Shape {     <strong>private int</strong> x, y, width, height;     <strong>public void</strong> draw(Canvas c) {         ...     } }</pre>
</blockquote>
<p>These classes can be drawn on a canvas:</p>
<blockquote>
<pre><strong>public class</strong> Canvas {     <strong>public void</strong> draw(Shape s) {         s.draw(<strong>this</strong>);    } }</pre>
</blockquote>
<p>Any drawing will typically contain a number of shapes. Assuming that they are represented as a list, it would be convenient to have a method in <code>Canvas</code> that draws them all:</p>
<blockquote>
<pre><strong>public void</strong> drawAll(List&lt;Shape&gt; shapes) {     <strong>for</strong> (Shape s: shapes) {         s.draw(<strong>this</strong>);    } }</pre>
</blockquote>
<p>Now, the type rules say that <code>drawAll()</code> can only be called on lists of exactly <code>Shape</code>: it cannot, for instance, be called on a <code>List&lt;Circle&gt;</code>. That is unfortunate, since all the method does is read shapes from the list, so it could just as well be called on a <code>List&lt;Circle&gt;</code>. What we really want is for the method to accept a list of <strong>any</strong> kind of shape:</p>
<blockquote>
<pre><strong>public void</strong> drawAll(List&lt;? <strong>extends</strong> Shape&gt; shapes) {     ... }</pre>
</blockquote>
<p>There is a small but very important difference here: we have replaced the type <code>List&lt;Shape&gt;</code> with <code>List&lt;? <strong>extends</strong>Shape&gt;</code>. Now <code>drawAll()</code> will accept lists of any subclass of <code>Shape</code>, so we can now call it on a <code>List&lt;Circle&gt;</code> if we want.<code>List&lt;? <strong>extends</strong> Shape&gt;</code> is an example of a <em>bounded wildcard</em>. The <code>?</code> stands for an unknown type, just like the wildcards we saw earlier. However, in this case, we know that this unknown type is in fact a subtype of <code>Shape</code>. (Note: It could be <code>Shape</code> itself, or some subclass; it need not literally extend <code>Shape</code>.) We say that <code>Shape</code> is the <em>upper bound</em>of the wildcard.There is, as usual, a price to be paid for the flexibility of using wildcards. That price is that it is now illegal to write into <code>shapes</code> in the body of the method. For instance, this is not allowed:</p>
<blockquote>
<pre><strong>public void</strong> addRectangle(List&lt;? <strong>extends</strong> Shape&gt; shapes) {     shapes.add(0, <strong>new</strong> Rectangle()); // <em>Compile-time error!</em> }</pre>
</blockquote>
<p>You should be able to figure out why the code above is disallowed. The type of the second parameter to <code>shapes.add()</code>is <code>? <strong>extends</strong> Shape</code>&#8211; an unknown subtype of <code>Shape<br />
ode&gt;. Since we don't know what type it is, we don't know if it is a supertype of <code>Rectangle</code>; it might or might not be such a supertype, so it isn't safe to pass a <code>Rectangle</code> there.Bounded wildcards are just what one needs to handle the example of the DMV passing its data to the census bureau. Our example assumes that the data is represented by mapping from names (represented as strings) to people (represented by reference types such as <code>Person</code> or its subtypes, such as <code>Driver</code>). <code>Map&lt;K,V&gt;</code> is an example of a generic type that takes two type arguments, representing the keys and values of the map.Again, note the naming convention for formal type parameters--<code>K</code> for keys and <code>V</code> for values.<br />
</code></p>
<blockquote>
<pre><strong>public class</strong> Census {     <strong>public static void</strong> addRegistry(Map&lt;String, ? <strong>extends</strong> Person&gt; registry) { } ...  Map&lt;String, Driver&gt; allDrivers = ... ; Census.addRegistry(allDrivers);</pre>
</blockquote>
</blockquote>
<p><span class="Apple-style-span" style="font-family: verdana; font-size: 12px; line-height: 18px;"> 转自:http://www.blogjava.net/killme2008/archive/2007/06/05/122174.html</span><span class="Apple-style-span" style="font-family: verdana; font-size: 12px; line-height: 18px;"> 泛型引入java语言已经有很长一段时间了，在JDK5出来的时候也非常认真地学习过，不过学习的资料都是网上泛滥并且重复的教程。这几天下了《The Java Programming Language》的第4版，准备把jdk5引入的新东西再重新系统地学习一次，同时再次回顾下java基础。今天记录下学习泛型那一章的注意点。<span style="font-weight: bold;">一、泛型类型的声明</span><span style="font-weight: bold;">1</span>.需要着重注意的一点，比如声明类Cell&lt;E&gt;：</span></p>
<p style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><span style="color: #0000ff;">package</span><span style="color: #000000;"> net.rubyeye.javaprogramming.generic;</span></p>
<p><span style="color: #0000ff;">public</span><span style="color: #000000;"> </span><span style="color: #0000ff;">class</span><span style="color: #000000;"> Cell</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">E</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> { </span><span style="color: #0000ff;">private</span><span style="color: #000000;"> Cell</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">E</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> next;</span> <span style="color: #0000ff;">private</span><span style="color: #000000;"> E element;</span> <span style="color: #0000ff;">public</span><span style="color: #000000;"> Cell(E element) { </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.element </span><span style="color: #000000;">=</span><span style="color: #000000;"> element;    }</span> <span style="color: #0000ff;">public</span><span style="color: #000000;"> Cell(E element, Cell</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">E</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> next) { </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.next </span><span style="color: #000000;">=</span><span style="color: #000000;"> next; </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.element </span><span style="color: #000000;">=</span><span style="color: #000000;"> element;    }</span> <span style="color: #0000ff;">public</span><span style="color: #000000;"> E getElement() { </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> element;    }</span> <span style="color: #0000ff;">public</span><span style="color: #000000;"> </span><span style="color: #0000ff;">void</span><span style="color: #000000;"> setElement(E element) { </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.element </span><span style="color: #000000;">=</span><span style="color: #000000;"> element;    }</span> <span style="color: #0000ff;">public</span><span style="color: #000000;"> Cell</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">E</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> getNext() { </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> next;    }</span> <span style="color: #0000ff;">public</span><span style="color: #000000;"> </span><span style="color: #0000ff;">void</span><span style="color: #000000;"> setNext(Cell</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">E</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> next) { </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.next </span><span style="color: #000000;">=</span><span style="color: #000000;"> next;    }</span>}然后如此使用：</p>
<p style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><span style="color: #000000;">Cell</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">String</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> strCell </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> Cell</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">String</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">(</span><span style="color: #000000;">&#8220;</span><span style="color: #000000;">Hello</span><span style="color: #000000;">&#8220;</span><span style="color: #000000;">);Cell</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Integer</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> intCell </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> Cell</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Integer</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">(</span><span style="color: #000000;">25</span><span style="color: #000000;">);</span>那么Cell&lt;String&gt;和Cell&lt;Integer&gt;是两个类吗？不，他们是同一个类，通过下面的实验证明：</p>
<p style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><span style="color: #000000;">assertTrue(strCell.getClass() </span><span style="color: #000000;">==</span><span style="color: #000000;"> intCell.getClass()));</span>java泛型的实现采用的“擦拭法”，Cell&lt;E&gt;仍然是一个类，无论E被任何具体的类型所替代。 <span style="font-weight: bold;">2</span>.泛型的类型参数不能用于static变量、static方法和static初始化，比如下面的使用方式都不能编译通过：</p>
<p style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><span style="color: #0000ff;">public</span><span style="color: #000000;"> </span><span style="color: #0000ff;">class</span><span style="color: #000000;"> Cell</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">E</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> { </span><span>private</span><span style="color: #000000;"> </span><span style="color: #0000ff;">static</span><span style="color: #000000;"> Cell</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">E</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> next; </span><span style="color: #0000ff;">private</span><span style="color: #000000;"> </span><span style="color: #0000ff;">static</span><span style="color: #000000;"> </span><span style="color: #0000ff;">void</span><span style="color: #000000;"> test(E e){            } </span>同样，静态方法是与类相关联的，调用也只能通过类，假设Cell有一个静态方法test，怎么调用才是正确的呢?</p>
<p style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><span style="color: #000000;">Cell</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">E</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">.test(); </span><span style="color: #008000;">//</span><span style="color: #008000;">编译错误</span><span style="color: #000000;">Cell</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">String</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">.test(); </span><span style="color: #008000;">//</span><span style="color: #008000;">同样编译错误</span><span style="color: #000000;">Cell.test(); </span><span style="color: #008000;">//</span><span style="color: #008000;">正确的方式</span>类似的，泛型的类型参数不能用于声明数组类型,比如下面的代码同样无法编译通过：</p>
<p style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><span style="color: #0000ff;">class</span><span style="color: #000000;"> SingleLinkQueue</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">E</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> { </span><span style="color: #008000;">//</span><span style="color: #008000;"> <img style="border: 0px initial initial;" src="http://www.blogjava.net/Images/dot.gif" alt="" /></span><span style="color: #000000;"> </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> E[] toArray() { </span><span style="color: #008000;">//</span><span style="color: #008000;"><img style="border: 0px initial initial;" src="http://www.blogjava.net/Images/dot.gif" alt="" /></span><span style="color: #000000;"> }}</span></p>
<p style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><span style="font-weight: bold;">3</span>.类型参数可以继承其他的类和接口，如果有多个接口可以用&amp;符号连接，通过extend参数限制了类型参数的范围，比如：</p>
<p style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><span style="color: #0000ff;">interface</span><span style="color: #000000;"> SortedCharSeqCollection</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">E </span><span style="color: #0000ff;">extends</span><span style="color: #000000;"> Comparable</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">E</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> </span><span style="color: #000000;">&amp;</span><span style="color: #000000;"> CharSequence</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> { </span><span style="color: #008000;">//</span><span style="color: #008000;"> <img style="border: 0px initial initial;" src="http://www.blogjava.net/Images/dot.gif" alt="" /> sorted char sequence collection methods <img style="border: 0px initial initial;" src="http://www.blogjava.net/Images/dot.gif" alt="" /></span><span style="color: #000000;">}</span></p>
<p style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;">SortedCharSeqCollection的类型参数E强制继承自Comparable和CharSequence接口，也就是替代的具体的类型参数必须实现这两个接口，从而限制了类型参数（type parameter)。<span style="font-weight: bold;">4</span>.比较有趣的内部类的泛型，对于静态内部类的类型参数可以与外部类的类型参数名不一样，静态内部类的类型参数与外部类的类型参数其实没有一点关系，比如：</p>
<p style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><span style="color: #0000ff;">class</span><span style="color: #000000;"> SingleLinkQueue</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">E</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> { </span><span style="color: #0000ff;">static</span><span style="color: #000000;"> </span><span style="color: #0000ff;">class</span><span style="color: #000000;"> Cell</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">E</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> { </span><span style="color: #0000ff;">private</span><span style="color: #000000;"> Cell</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">E</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> next; </span><span style="color: #0000ff;">private</span><span style="color: #000000;"> E element; </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> Cell(E element) { </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.element </span><span style="color: #000000;">=</span><span style="color: #000000;"> element;        } </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> Cell(E element, Cell</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">E</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> next) { </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.element </span><span style="color: #000000;">=</span><span style="color: #000000;"> element; </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.next </span><span style="color: #000000;">=</span><span style="color: #000000;"> next;        } </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> E getElement() { </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> element;        } </span><span style="color: #008000;">/*</span><span style="color: #008000;"> <img style="border: 0px initial initial;" src="http://www.blogjava.net/Images/dot.gif" alt="" /> rest of Cell methods as before <img style="border: 0px initial initial;" src="http://www.blogjava.net/Images/dot.gif" alt="" /> </span><span style="color: #008000;">*/</span><span style="color: #000000;"> }</span> <span style="color: #0000ff;">protected</span><span style="color: #000000;"> Cell</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">E</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> head; </span><span style="color: #0000ff;">protected</span><span> Cell</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">E</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> tail;</span> <span style="color: #008000;">/*</span><span style="color: #008000;"> <img style="border: 0px initial initial;" src="http://www.blogjava.net/Images/dot.gif" alt="" /> rest of SingleLinkQueue methods as before <img style="border: 0px initial initial;" src="http://www.blogjava.net/Images/dot.gif" alt="" /> </span><span style="color: #008000;">*/</span><span style="color: #000000;">}</span>Cell&lt;E&gt;类的声明和SingleLinkQueue&lt;E&gt; 两个类中的E仅仅是名称相同，他们之间的关联是通过head和tail的声明才关联在一起，你可以将Cell&lt;E&gt;中的E改成F也没关系，比如：</p>
<p style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><span style="color: #0000ff;">package</span><span style="color: #000000;"> net.rubyeye.javaprogramming.generic;</span></p>
<p><span style="color: #0000ff;">class</span><span style="color: #000000;"> AnotherSingleLinkQueue</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">E</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> { </span></p>
<p><span style="color: #0000ff;">static</span><span style="color: #000000;"> </span><span style="color: #0000ff;">class</span><span style="color: #000000;"> Cell</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">F</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> { </span></p>
<p><span style="color: #0000ff;">private</span><span style="color: #000000;"> Cell</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">F</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> next;</span> <span style="color: #0000ff;">private</span><span style="color: #000000;"> F element;</span></p>
<p><span style="color: #0000ff;">public</span><span style="color: #000000;"> Cell(F element) { </span></p>
<p><span style="color: #0000ff;">this</span><span style="color: #000000;">.element </span><span style="color: #000000;">=</span><span style="color: #000000;"> element;        }</span></p>
<p><span style="color: #0000ff;">public</span><span style="color: #000000;"> Cell(F element, Cell</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">F</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> next) { </span></p>
<p><span style="color: #000000;"> </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.element </span><span style="color: #000000;">=</span><span style="color: #000000;"> element; </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.next </span><span style="color: #000000;">=</span><span style="color: #000000;"> next; </span></p>
<p><span style="color: #000000;"> }</span></p>
<p><span style="color: #0000ff;">public</span><span style="color: #000000;"> F getElement() { </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> element;        } </span><span style="color: #008000;">/*</span><span style="color: #008000;"> <img style="border: 0px initial initial;" src="http://www.blogjava.net/Images/dot.gif" alt="" /> rest of Cell methods as before <img style="border: 0px initial initial;" src="http://www.blogjava.net/Images/dot.gif" alt="" /></span></p>
<p><span style="color: #008000;"> </span><span style="color: #008000;">*/</span><span style="color: #000000;"> }</span> <span style="color: #0000ff;">protected</span><span style="color: #000000;"> Cell</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">E</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> head;</span> <span style="color: #0000ff;">protected</span><span style="color: #000000;"> Cell</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">E</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> tail;</span> <span style="color: #008000;">/*</span><span style="color: #008000;"> <img style="border: 0px initial initial;" src="http://www.blogjava.net/Images/dot.gif" alt="" /> rest of SingleLinkQueue methods as before <img style="border: 0px initial initial;" src="http://www.blogjava.net/Images/dot.gif" alt="" /> </span><span style="color: #008000;">*/</span><span style="color: #000000;">}</span>而一般的内部类就不一样了，内部类可以直接使用外部类的类型参数甚至隐藏。</p>
<p><span style="font-weight: bold;">二、子类型与通配符</span>今天读了第2节，泛型的使用比我原先所知的更为复杂，java语法本来以简洁优美著称，随着java5,java7的到来，语法是越来越复杂，甚至可以说丑陋!-_-    要知道一点，比如List&lt;Integer&gt;不是List&lt;Number&gt;的子类，而是Collection&lt;Integer&gt;的子类。因为List&lt;Integer&gt;和List&lt;Number&gt;的类型是一样的，都是List。那么如何表示参数化类型是Number的子类呢？这就需要用到通配符：</p>
<p style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><span style="color: #000000;">List</span><span style="color: #000000;">&lt;?</span><span style="color: #000000;"> </span><span style="color: #0000ff;">extends</span><span style="color: #000000;"> Number</span><span style="color: #000000;">&gt;</span></p>
<p>表示类型变量是Number或者Number的子类。这个就是所谓的上界通配符，同样，如果要表示类型变量是Number或者Number的super type，可以使用下界通配符：</p>
<p style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><span style="color: #000000;">List</span><span style="color: #000000;">&lt;?</span><span style="color: #000000;"> </span><span style="color: #0000ff;">super</span><span style="color: #000000;"> Number</span><span style="color: #000000;">&gt;</span></p>
<p>而通配符List&lt;?&gt;等价于：</p>
<p style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><span style="color: #000000;">List</span><span style="color: #000000;">&lt;?</span><span style="color: #000000;"> </span><span style="color: #0000ff;">extends</span><span style="color: #000000;"> Object</span><span style="color: #000000;">&gt;</span></p>
<p>通配符只能用于变量、局部变量、参数类型和返回类型，不能用于命名类和接口。比如下面的代码将不能编译通过：</p>
<p style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><span style="color: #0000ff;">class</span><span style="color: #000000;"> MyList </span><span style="color: #0000ff;">implements</span><span style="color: #000000;"> List</span><span style="color: #000000;">&lt;?&gt;</span><span style="color: #000000;">{ </span><span style="color: #008000;">//</span><span style="color: #008000;"><img style="border: 0px initial initial;" src="http://www.blogjava.net/Images/dot.gif" alt="" /></span><span style="color: #000000;">}</span> 通配符有另一个问题：因为通配符代表的是未知的类型，你不能在任何需要类型信息的地方使用它。比如下面的代码同样无法编译通过：</p>
<p>&gt;</p>
<p style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><span style="color: #000000;">SingleLinkQueue</span><span style="color: #000000;">&lt;?&gt;</span><span style="color: #000000;"> strings </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> SingleLinkQueue</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">String</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">();strings.add(</span><span style="color: #000000;">&#8220;</span><span style="color: #000000;">Hello</span><span style="color: #000000;">&#8220;</span><span style="color: #000000;">); </span><span style="color: #008000;">//</span><span style="color: #008000;"> INVALID: 无法编译</span><span style="color: #000000;">SingleLinkQueue</span><span style="color: #000000;">&lt;?</span><span style="color: #000000;"> </span><span style="color: #0000ff;">extends</span><span style="color: #000000;"> Number</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> numbers </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> SingleLinkQueue</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Number</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">();numbers.add(Integer.valueOf(</span><span style="color: #000000;">25</span><span style="color: #000000;">)); </span><span style="color: #008000;">//</span><span style="color: #008000;"> INVALID: 无法编译</span><span style="font-weight: bold;">三、泛型方法和类型推断</span> 如果我们想参数化方法的参数和返回值的类型，这就引出了泛型方法的声明，声明一个泛型方法的方式如下：</p>
<p style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><span style="color: #000000;">&lt;</span><span style="color: #000000;">T</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> T passThrough(T obj) { </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> obj;}</span>这个方法限制传入的参数的类型与返回的参数类型将一致，可以看到，在方法签名前加上&lt;T&gt;即可。我们可以这样调用这个方法：</p>
<p style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><span style="color: #000000;">String s1 </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #000000;">&#8220;</span><span style="color: #000000;">Hello</span><span style="color: #000000;">&#8220;</span><span style="color: #000000;">;String s2 </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">String</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">passThrough(s1);</span>这样的调用是不是比较奇怪？幸好提供了<span style="font-weight: bold;">类型推断</span>，根据参数的类型来自动判断方法的类型（比如返回值类型），因此可以直接调用：</p>
<p style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><span style="color: #000000;">String s1 </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #000000;">&#8220;</span><span style="color: #000000;">Hello</span><span style="color: #000000;">&#8220;</span><span style="color: #000000;">;String s2 </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.passThrough(s1);</span> 如果方法有两个类型变量，类型推断将怎么处理呢？比如：</p>
<p style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><span style="color: #000000;">&lt;</span><span style="color: #000000;">T</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> T passThrough(T obj1,T obj2) { </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> (T)(obj1.toString()</span><span style="color: #000000;">+</span><span style="color: #000000;">obj2.toString());    }</span>然后我们传入两个参数，一个String，一个int，那么返回什么呢？</p>
<p style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><span style="color: #000000;">String s1</span><span style="color: #000000;">=</span><span style="color: #000000;">&#8220;</span><span style="color: #000000;">test</span><span style="color: #000000;">&#8220;</span><span style="color: #000000;">;String s3</span><span style="color: #000000;">=</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.passThrough(s1, </span><span style="color: #000000;">1</span><span style="color: #000000;">); </span><span style="color: #008000;">//</span><span style="color: #008000;">编译出错</span>类型推断是比较复杂的，这里将返回的将是Object类型，是传入的参数类型的<span style="font-weight: bold;">交集</span></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.zye.me/2010/02/50190.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

