<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>
<channel>
	<title>Comments on: Java and .NET Generics</title>
	<atom:link href="http://www.buunguyen.net/blog/java-and-net-generics.html/feed" rel="self" type="application/rss+xml" />
	<link>http://www.buunguyen.net/blog/java-and-net-generics.html</link>
	<description>Thoughts on software development and project management</description>
	<pubDate>Thu, 20 Nov 2008 23:19:48 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.2</generator>
		<item>
		<title>By: Buu Nguyen</title>
		<link>http://www.buunguyen.net/blog/java-and-net-generics.html#comment-43819</link>
		<dc:creator>Buu Nguyen</dc:creator>
		<pubDate>Wed, 03 Sep 2008 07:43:05 +0000</pubDate>
		<guid isPermaLink="false">http://www.buunguyen.net/blog/?p=10#comment-43819</guid>
		<description>Anyone interested in why methods accepting two generic types &#038; having different return type are not considered by the compiler as a naming clash may refer to this explanation: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6182950</description>
		<content:encoded><![CDATA[<p>Anyone interested in why methods accepting two generic types &#038; having different return type are not considered by the compiler as a naming clash may refer to this explanation: <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6182950" rel="nofollow">http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6182950</a></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Buu Nguyen&#8217;s Blog &#187; Microsoft is dead</title>
		<link>http://www.buunguyen.net/blog/java-and-net-generics.html#comment-1845</link>
		<dc:creator>Buu Nguyen&#8217;s Blog &#187; Microsoft is dead</dc:creator>
		<pubDate>Wed, 11 Apr 2007 17:41:49 +0000</pubDate>
		<guid isPermaLink="false">http://www.buunguyen.net/blog/?p=10#comment-1845</guid>
		<description>[...] is that despite being big, innovations are still happening at MS. Think about cool stuffs like .NET generics, Windows Workflow Foundation, Orcas, Office SharePoint Server 2007, C# 3.0, WPF(/E) (the two techs [...]</description>
		<content:encoded><![CDATA[<p>[...] is that despite being big, innovations are still happening at MS. Think about cool stuffs like .NET generics, Windows Workflow Foundation, Orcas, Office SharePoint Server 2007, C# 3.0, WPF(/E) (the two techs [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Buu Nguyen</title>
		<link>http://www.buunguyen.net/blog/java-and-net-generics.html#comment-698</link>
		<dc:creator>Buu Nguyen</dc:creator>
		<pubDate>Wed, 21 Mar 2007 08:31:36 +0000</pubDate>
		<guid isPermaLink="false">http://www.buunguyen.net/blog/?p=10#comment-698</guid>
		<description>&lt;blockquote&gt;...fail in C#, because operators are early-bound, and the compiler isn't smart enough to bind them differently for different specializations. Then again, a comparable example will succeed in VB, because VB late-binds its operators.&lt;/blockquote&gt;
Are you sure this works in VB.NET?  T is not constrained and can be any type, the compiler should not compile to assure  type-safety.  I cannot get the VB.NET code compiled, with the same error message as the C# version &lt;i&gt;"Operator '+' is not defined for types 'T' and 'T'"&lt;/i&gt;, which I think expected.

&lt;blockquote&gt;public T add&#60;T&#62;(T a, T b) { return a+b; }
DoStuff(List&#60;String&#62; list)
DoStuff(Listt&#60;Integer&#62; list)&lt;/blockquote&gt;
I would think the same, but when I tried it out, it turned out that if both DoStuff methods return the same type, then it would not compile, as expected, but if they return different types, then it compiled just fine.
&lt;div class="ch_code_container"&gt;&lt;pre&gt; public static String DoStuff(List&lt;String&gt; list) {
    return null;
 }
 public static int DoStuff(List&lt;Integer&gt; list) {
    return 0;
 }&lt;/pre&gt;

&lt;/div&gt;
I don't understand why it can possibly compile, and there is no "magic" in the generated bytecode.
&lt;div class="ch_code_container"&gt;
&lt;pre&gt; public static java.lang.String DoStuff(java.util.List);
 Code:
   0:   aconst_null
   1:   areturn

 public static int DoStuff(java.util.List);
 Code:
   0:   iconst_0
   1:   ireturn
&lt;/pre&gt;
&lt;/div&gt;
The above does not look like valid bytecode.  I'll need to look at the spec...</description>
		<content:encoded><![CDATA[<blockquote><p>&#8230;fail in C#, because operators are early-bound, and the compiler isn&#8217;t smart enough to bind them differently for different specializations. Then again, a comparable example will succeed in VB, because VB late-binds its operators.</p></blockquote>
<p>Are you sure this works in VB.NET?  T is not constrained and can be any type, the compiler should not compile to assure  type-safety.  I cannot get the VB.NET code compiled, with the same error message as the C# version <i>&#8220;Operator &#8216;+&#8217; is not defined for types &#8216;T&#8217; and &#8216;T&#8217;&#8221;</i>, which I think expected.</p>
<blockquote><p>public T add&lt;T&gt;(T a, T b) { return a+b; }<br />
DoStuff(List&lt;String&gt; list)<br />
DoStuff(Listt&lt;Integer&gt; list)</p></blockquote>
<p>I would think the same, but when I tried it out, it turned out that if both DoStuff methods return the same type, then it would not compile, as expected, but if they return different types, then it compiled just fine.</p>
<div class="ch_code_container">
<pre> public static String DoStuff(List<string> list) {
    return null;
 }
 public static int DoStuff(List<integer> list) {
    return 0;
 }</integer></string></pre>
</div>
<p>I don&#8217;t understand why it can possibly compile, and there is no &#8220;magic&#8221; in the generated bytecode.</p>
<div class="ch_code_container">
<pre> public static java.lang.String DoStuff(java.util.List);
 Code:
   0:   aconst_null
   1:   areturn

 public static int DoStuff(java.util.List);
 Code:
   0:   iconst_0
   1:   ireturn
</pre>
</div>
<p>The above does not look like valid bytecode.  I&#8217;ll need to look at the spec&#8230;</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Andrew Norris</title>
		<link>http://www.buunguyen.net/blog/java-and-net-generics.html#comment-471</link>
		<dc:creator>Andrew Norris</dc:creator>
		<pubDate>Sun, 18 Mar 2007 05:01:53 +0000</pubDate>
		<guid isPermaLink="false">http://www.buunguyen.net/blog/?p=10#comment-471</guid>
		<description>Arrgh. Hopefully this will render the examples properly:

public T add&#60;T&#62;(T a, T b) { return a+b; }

DoStuff(List&#60;String&#62; list)
DoStuff(Listt&#60;Integer&#62; list)</description>
		<content:encoded><![CDATA[<p>Arrgh. Hopefully this will render the examples properly:</p>
<p>public T add&lt;T&gt;(T a, T b) { return a+b; }</p>
<p>DoStuff(List&lt;String&gt; list)<br />
DoStuff(Listt&lt;Integer&gt; list)</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Andrew Norris</title>
		<link>http://www.buunguyen.net/blog/java-and-net-generics.html#comment-470</link>
		<dc:creator>Andrew Norris</dc:creator>
		<pubDate>Sun, 18 Mar 2007 04:59:59 +0000</pubDate>
		<guid isPermaLink="false">http://www.buunguyen.net/blog/?p=10#comment-470</guid>
		<description>Interesting.

My main complaint about C# generics is that arithmetic doesn't work:

public T add(T a, T b) { return a+b; }

will fail in C#, because operators are early-bound, and the compiler isn't smart enough to bind them differently for different specializations. Then again, a comparable example will succeed in VB, because VB late-binds its operators.

My main complaint about Java generics is that they break under method polymorphism, since they're not really different types. A method with the signatures:

DoStuff(List list)
DoStuff(List list)

will fail, despite the fact that you might legitimately need different implementations.</description>
		<content:encoded><![CDATA[<p>Interesting.</p>
<p>My main complaint about C# generics is that arithmetic doesn&#8217;t work:</p>
<p>public T add(T a, T b) { return a+b; }</p>
<p>will fail in C#, because operators are early-bound, and the compiler isn&#8217;t smart enough to bind them differently for different specializations. Then again, a comparable example will succeed in VB, because VB late-binds its operators.</p>
<p>My main complaint about Java generics is that they break under method polymorphism, since they&#8217;re not really different types. A method with the signatures:</p>
<p>DoStuff(List list)<br />
DoStuff(List list)</p>
<p>will fail, despite the fact that you might legitimately need different implementations.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Buu Nguyen</title>
		<link>http://www.buunguyen.net/blog/java-and-net-generics.html#comment-469</link>
		<dc:creator>Buu Nguyen</dc:creator>
		<pubDate>Sat, 17 Mar 2007 09:23:13 +0000</pubDate>
		<guid isPermaLink="false">http://www.buunguyen.net/blog/?p=10#comment-469</guid>
		<description>&lt;blockquote&gt;So, given that Java doesn't support collections of primitive types, the behaviour would seem identical.&lt;/blockquote&gt;
Do you mean behavior of generics of reference types in .NET and Java?  If it was what you meant, how come it is identical given the fact that type information is erased by the Java compiler?

&lt;blockquote&gt;You only get fair results if you restart your VM between each benchmark, and ideally 'warm up' the VM loading in the OS - as most OSs take longer to start the first instance of a process.&lt;/blockquote&gt;
It did indeed take ridiculous amount of time in the first run (I recalled it took 27 seconds to finish the 10,000,000 elements for ArrayList of Integer).  However, I did run the benchmark several times and only recorded the result when it looked stable.  As I rerun the benchmark again many times today, the results are just close to that.  Any idea?

&lt;blockquote&gt;If I don't reply, drop me an email (ricky.clarkson@gmail.com)&lt;/blockquote&gt;
Thanks for your consideration, Ricky.  Just a suggestion if you are not aware of it: why don't you subscribe to this entry's RSS (you can see it at the end of the entry) :-)</description>
		<content:encoded><![CDATA[<blockquote><p>So, given that Java doesn&#8217;t support collections of primitive types, the behaviour would seem identical.</p></blockquote>
<p>Do you mean behavior of generics of reference types in .NET and Java?  If it was what you meant, how come it is identical given the fact that type information is erased by the Java compiler?</p>
<blockquote><p>You only get fair results if you restart your VM between each benchmark, and ideally &#8216;warm up&#8217; the VM loading in the OS - as most OSs take longer to start the first instance of a process.</p></blockquote>
<p>It did indeed take ridiculous amount of time in the first run (I recalled it took 27 seconds to finish the 10,000,000 elements for ArrayList of Integer).  However, I did run the benchmark several times and only recorded the result when it looked stable.  As I rerun the benchmark again many times today, the results are just close to that.  Any idea?</p>
<blockquote><p>If I don&#8217;t reply, drop me an email (ricky.clarkson@gmail.com)</p></blockquote>
<p>Thanks for your consideration, Ricky.  Just a suggestion if you are not aware of it: why don&#8217;t you subscribe to this entry&#8217;s RSS (you can see it at the end of the entry) <img src='http://www.buunguyen.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Ricky Clarkson</title>
		<link>http://www.buunguyen.net/blog/java-and-net-generics.html#comment-454</link>
		<dc:creator>Ricky Clarkson</dc:creator>
		<pubDate>Sat, 17 Mar 2007 03:26:50 +0000</pubDate>
		<guid isPermaLink="false">http://www.buunguyen.net/blog/?p=10#comment-454</guid>
		<description>So the code sharing works the same for all non-primitive types?  I see.  It seems that .NET terminology says non-value, not non-primitive.  So, given that Java doesn't support collections of primitive types, the behaviour would seem identical.

By VM instance, I meant the actual running VM.  You only get fair results if you restart your VM between each benchmark, and ideally 'warm up' the VM loading in the OS - as most OSs take longer to start the first instance of a process.  If there's any overlap between two tests, the JIT may kick in and skew the results.  Of course, you could turn the JIT off, but then your results are skewed in a different way.

If I don't reply, drop me an email (ricky.clarkson@gmail.com).  I only spotted this reply because my RSS reader told me that the dzone link had been promoted.</description>
		<content:encoded><![CDATA[<p>So the code sharing works the same for all non-primitive types?  I see.  It seems that .NET terminology says non-value, not non-primitive.  So, given that Java doesn&#8217;t support collections of primitive types, the behaviour would seem identical.</p>
<p>By VM instance, I meant the actual running VM.  You only get fair results if you restart your VM between each benchmark, and ideally &#8216;warm up&#8217; the VM loading in the OS - as most OSs take longer to start the first instance of a process.  If there&#8217;s any overlap between two tests, the JIT may kick in and skew the results.  Of course, you could turn the JIT off, but then your results are skewed in a different way.</p>
<p>If I don&#8217;t reply, drop me an email (ricky.clarkson@gmail.com).  I only spotted this reply because my RSS reader told me that the dzone link had been promoted.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Buu Nguyen</title>
		<link>http://www.buunguyen.net/blog/java-and-net-generics.html#comment-442</link>
		<dc:creator>Buu Nguyen</dc:creator>
		<pubDate>Fri, 16 Mar 2007 06:15:28 +0000</pubDate>
		<guid isPermaLink="false">http://www.buunguyen.net/blog/?p=10#comment-442</guid>
		<description>&lt;blockquote&gt;What is the criteria the CLR uses to decide whether to share the code or not?&lt;/blockquote&gt;
If a method of generic type or a type parameterized method is already JIT-compiled for a specific reference type, then it will be reused when the code of the same method is needed for any other reference types.  The same does not hold for value types since the internal representation of them are different, thus unique method code must exist for each type.  For structs, those with the same internal layout will share the same x86 code.

&lt;blockquote&gt;Space inefficiency works out to be time inefficiency, quite often, because of cache misses (lack of memory locality).&lt;/blockquote&gt;
I agree, if the space inefficiency is big enough.  In the CLR case, the runtime code sharing would, hopefully, prevent excessive space inefficiency.

&lt;blockquote&gt;The benchmarking code is flawed because the same VM instance is used for all code&lt;/blockquote&gt;
I did it on JDK 5 - update 11, which is the latest.  I believe there is better way to do the benchmark but I do not quite understand why it is flawed.  What do you suggest to benchmark to be done differently?

&lt;blockquote&gt;That's what Bracha's optional typing is about; worth a Google.&lt;/blockquote&gt;
I'll definitely take a look at that.

&lt;blockquote&gt;You'd need some type that was a List plus a type token for that...&lt;/blockquote&gt;
Thanks for sharing the code.  This emulation is helpful in several use cases.

Again, thanks a lot for offering your insights into the topic, Ricky.</description>
		<content:encoded><![CDATA[<blockquote><p>What is the criteria the CLR uses to decide whether to share the code or not?</p></blockquote>
<p>If a method of generic type or a type parameterized method is already JIT-compiled for a specific reference type, then it will be reused when the code of the same method is needed for any other reference types.  The same does not hold for value types since the internal representation of them are different, thus unique method code must exist for each type.  For structs, those with the same internal layout will share the same x86 code.</p>
<blockquote><p>Space inefficiency works out to be time inefficiency, quite often, because of cache misses (lack of memory locality).</p></blockquote>
<p>I agree, if the space inefficiency is big enough.  In the CLR case, the runtime code sharing would, hopefully, prevent excessive space inefficiency.</p>
<blockquote><p>The benchmarking code is flawed because the same VM instance is used for all code</p></blockquote>
<p>I did it on JDK 5 - update 11, which is the latest.  I believe there is better way to do the benchmark but I do not quite understand why it is flawed.  What do you suggest to benchmark to be done differently?</p>
<blockquote><p>That&#8217;s what Bracha&#8217;s optional typing is about; worth a Google.</p></blockquote>
<p>I&#8217;ll definitely take a look at that.</p>
<blockquote><p>You&#8217;d need some type that was a List plus a type token for that&#8230;</p></blockquote>
<p>Thanks for sharing the code.  This emulation is helpful in several use cases.</p>
<p>Again, thanks a lot for offering your insights into the topic, Ricky.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Ricky Clarkson</title>
		<link>http://www.buunguyen.net/blog/java-and-net-generics.html#comment-432</link>
		<dc:creator>Ricky Clarkson</dc:creator>
		<pubDate>Fri, 16 Mar 2007 02:40:31 +0000</pubDate>
		<guid isPermaLink="false">http://www.buunguyen.net/blog/?p=10#comment-432</guid>
		<description>"First, I assume you know that a generic type representation will not be created unless it is used. Second, even if you have 10000 types, chances are that a significant amount of these (those of reference types) are enforced by the CLR to share the same JIT-compiled x86 code."

I assumed the former, and didn't realise the latter.  What is the criteria the CLR uses to decide whether to share the code or not?  It is at least interesting that the CLR has the choice as to whether to share the code or not, which the JVM does not have.

"Finally, I see this as an inefficiency of space, not of time."

Space inefficiency works out to be time inefficiency, quite often, because of cache misses (lack of memory locality).

The benchmarking code is flawed because the same VM instance is used for all code.  I haven't read it properly, because of that, though I appreciate your attention to detail there.

"Finally, I do not see why the compilers should not disallow really ridiculous stuffs like casting a list of int to a list of string."

Because that cast might be desirable when you are only halfway through generifying some code.  It is actually a good thing, if you are working with good programmers, to allow arguably crap code, but to tell the developer how crap the code is.  That's what Bracha's optional typing is about; worth a Google.   

"Letâ€™s say I need to know if an instance of list is a list of String a list of Integer, can I do that with type tokens?"

No.  You'd need some type that was a List plus a type token for that.  E.g.:

class ListPlusTypeToken&#60;E&#62;
{
    public final List&#60;E&#62; list;
    public final Class&#60;E&#62; type;

    public ListPlusTypeToken(List&#60;E&#62; list,Class&#60;E&#62; type)
    {
        this.list=list;
        this.type=type;
    } 
}</description>
		<content:encoded><![CDATA[<p>&#8220;First, I assume you know that a generic type representation will not be created unless it is used. Second, even if you have 10000 types, chances are that a significant amount of these (those of reference types) are enforced by the CLR to share the same JIT-compiled x86 code.&#8221;</p>
<p>I assumed the former, and didn&#8217;t realise the latter.  What is the criteria the CLR uses to decide whether to share the code or not?  It is at least interesting that the CLR has the choice as to whether to share the code or not, which the JVM does not have.</p>
<p>&#8220;Finally, I see this as an inefficiency of space, not of time.&#8221;</p>
<p>Space inefficiency works out to be time inefficiency, quite often, because of cache misses (lack of memory locality).</p>
<p>The benchmarking code is flawed because the same VM instance is used for all code.  I haven&#8217;t read it properly, because of that, though I appreciate your attention to detail there.</p>
<p>&#8220;Finally, I do not see why the compilers should not disallow really ridiculous stuffs like casting a list of int to a list of string.&#8221;</p>
<p>Because that cast might be desirable when you are only halfway through generifying some code.  It is actually a good thing, if you are working with good programmers, to allow arguably crap code, but to tell the developer how crap the code is.  That&#8217;s what Bracha&#8217;s optional typing is about; worth a Google.   </p>
<p>&#8220;Letâ€™s say I need to know if an instance of list is a list of String a list of Integer, can I do that with type tokens?&#8221;</p>
<p>No.  You&#8217;d need some type that was a List plus a type token for that.  E.g.:</p>
<p>class ListPlusTypeToken&lt;E&gt;<br />
{<br />
    public final List&lt;E&gt; list;<br />
    public final Class&lt;E&gt; type;</p>
<p>    public ListPlusTypeToken(List&lt;E&gt; list,Class&lt;E&gt; type)<br />
    {<br />
        this.list=list;<br />
        this.type=type;<br />
    }<br />
}</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Ricky Clarkson</title>
		<link>http://www.buunguyen.net/blog/java-and-net-generics.html#comment-415</link>
		<dc:creator>Ricky Clarkson</dc:creator>
		<pubDate>Thu, 15 Mar 2007 01:35:38 +0000</pubDate>
		<guid isPermaLink="false">http://www.buunguyen.net/blog/?p=10#comment-415</guid>
		<description>There's no reason why .NET needs to have a separate runtime representation of each.  If you made one collection each for 10,000 types, and used it once, then the code-sharing approach would be faster.  That's an extreme, of course; I don't know at what point in a reasonable app the opposite approach would become a problem.

Have you got hard data that shows that .NET collections are faster, or is this speculation?  It would be valid for the Hotspot VM to eliminate casts if it can be certain that they would always pass.  Remember that casts are only actually checks at runtime.

The example of really stupid code in Java relies on the developer ignoring compile warnings, i.e., it relies on the intentionally-stupid developer.

One advantage of the erasure approach is that the stupid code is compilable, and testable, so one can generify their code in small stages, rather than having to generify everywhere before testing.  Now, that wouldn't matter so much, because the IDEs have caught up with the language sufficiently, but in the early days of Java 5, the IDEs didn't know where they were.

Reification is proposed for Java 7.

Marcos - reflection can be emulated through the use of type tokens.

Buu Nguyen - Generics information exists in class files.  It doesn't exist for local variables.  Everywhere else it does.</description>
		<content:encoded><![CDATA[<p>There&#8217;s no reason why .NET needs to have a separate runtime representation of each.  If you made one collection each for 10,000 types, and used it once, then the code-sharing approach would be faster.  That&#8217;s an extreme, of course; I don&#8217;t know at what point in a reasonable app the opposite approach would become a problem.</p>
<p>Have you got hard data that shows that .NET collections are faster, or is this speculation?  It would be valid for the Hotspot VM to eliminate casts if it can be certain that they would always pass.  Remember that casts are only actually checks at runtime.</p>
<p>The example of really stupid code in Java relies on the developer ignoring compile warnings, i.e., it relies on the intentionally-stupid developer.</p>
<p>One advantage of the erasure approach is that the stupid code is compilable, and testable, so one can generify their code in small stages, rather than having to generify everywhere before testing.  Now, that wouldn&#8217;t matter so much, because the IDEs have caught up with the language sufficiently, but in the early days of Java 5, the IDEs didn&#8217;t know where they were.</p>
<p>Reification is proposed for Java 7.</p>
<p>Marcos - reflection can be emulated through the use of type tokens.</p>
<p>Buu Nguyen - Generics information exists in class files.  It doesn&#8217;t exist for local variables.  Everywhere else it does.</p>
]]></content:encoded>
	</item>
</channel>
</rss>
