<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:xhtml="http://www.w3.org/1999/xhtml">
  <title>
      Two Java Type‐System Holes
     | Two 〈Foo〉s Walk into a 〈Bar〉</title>
  
  <updated>2009-08-22T17:59:00-05:00</updated>
  <author>
    <name>Chris Povirk</name>
    <email>beigetangerine@gmail.com</email>
    <uri>http://twofoos.org/</uri>
  </author>
  <link rel="alternate" type="application/xhtml+xml" hreflang="en" href="http://twofoos.org/content/java-type-system-holes/"/>
  <link rel="self" type="application/atom+xml" href="http://twofoos.org/content/java-type-system-holes/feed/"/>
  <rights>Copyright © 2003–2015 Chris Povirk.  All Rights Reserved.</rights>
  <id>http://twofoos.org/</id>
  <generator uri="http://twofoos.org/content/splat/" version="1.0">SPLAT</generator>
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
<entry>
    <updated>2009-08-22T17:59:00-05:00</updated>
    <summary>
            New: A small oversight and a big puzzler.</summary>
    <title type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">Two Java Type‐System Holes</div>
    </title>
    <link rel="alternate" type="application/xhtml+xml" href="http://twofoos.org/content/java-type-system-holes/#update_2009-08-22T17:59:00-05:00"/>
    <id>http://twofoos.org/content/java-type-system-holes/#update_2009-08-22T17:59:00-05:00</id>
    <category term="java"/>
    <content type="xhtml" xml:base="http://twofoos.org/">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <strong>initial posting</strong>
        <div>

    <div>
      <p>That is, two bugs in the language specification that allow a program to compile without warnings but to produce a <code>ClassCastException</code> at runtime on a line with no explicit cast.</p>
    </div>

    <xhtml:h3>Cast to Inner Class of Generic Type</xhtml:h3>
    <div>

    <xhtml:h4>Code</xhtml:h4>
    <div>
<blockquote><pre>class Outer&lt;E&gt; {
  Inner inner;

  class Inner {
    E e;

    E getOtherElement(Object other) {
      if (!(other instanceof Outer.Inner)) {
        throw new IllegalArgumentException(String.valueOf(other));
      }

      Inner that = (Inner) other;
      return that.e;
    }
  }

  public static void main(String[] args) {
    Outer&lt;String&gt; s = new Outer&lt;String&gt;();
    s.inner = s.new Inner();
    s.inner.e = "hello";

    Outer&lt;Integer&gt; i = new Outer&lt;Integer&gt;();
    i.inner = i.new Inner();
    i.inner.e = 1234;

    String producesClassCast = s.inner.getOtherElement(i.inner);
  }
}
</pre></blockquote>
    </div>

    <xhtml:h4>Output</xhtml:h4>
    <div>

<blockquote><pre>Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
  at Outer.main(Outer.java:26)</pre></blockquote>

    </div>

    <xhtml:h4>Explanation</xhtml:h4>
    <div>

<p>The Java language specification lacks rules about casts to inner classes.  Commonly used versions of javac happen to allow us to cast to <code>Inner</code> — that is, to cast to <code>Outer&lt;E&gt;.Inner</code> — without a warning.  <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6665356">The more honest version of the cast, <code>(Outer&lt;E&gt;.Inner)</code>, ought likewise to be permitted with a warning; it's rejected outright.</a></p>

<p>This subtle interaction between generics and inner classes pales in comparison to...</p>

    </div>

    </div>

    <xhtml:h3>Generic "Overrides" of Static Methods</xhtml:h3>
    <div>
    <xhtml:h4>Code</xhtml:h4>
    <div>
<blockquote><pre>import java.util.HashSet;
import static java.util.Collections.singleton;

class Printer {
  static &lt;E&gt; void print(Iterable&lt;E&gt; input) {
    for (E e : input) {
      System.out.println("Unsorted " + e);
    }
  }
}

class SortedPrinter extends Printer {
  static &lt;E extends Comparable&lt;? super E&gt;&gt; void print(Iterable&lt;E&gt; input) {
    for (E e : input) {
      System.out.println("Sorted " + e);
    }
  }
}

class Caller {
  public static void main(String[] args) {
    SortedPrinter.print(singleton(1));
    SortedPrinter.print(singleton(null));
    SortedPrinter.print(singleton(new HashSet&lt;Object&gt;()));
  }
}</pre></blockquote>
    </div>
    <xhtml:h4>Output</xhtml:h4>
    <div>

<blockquote><pre>Sorted 1
Sorted null
Exception in thread "main" java.lang.ClassCastException: java.util.HashSet cannot be cast to java.lang.Comparable
  at SortedPrinter.print(Caller.java:14)
  at Caller.main(Caller.java:24)</pre></blockquote>

    </div>
    <xhtml:h4>Explanation</xhtml:h4>
    <div>

<p>You need two obscure pieces of knowledge to understand this one:</p>
<ol>
  <li>
    At runtime, methods are identified by these four pieces of information:
    <ul>
      <li>return type</li>
      <li>class name</li>
      <li>method name</li>
      <li>argument types</li>
    </ul>

    (Note the absence of anything related to type parameters.)
  </li>

  <li style="margin-top: 2em;">
    Indirect references to static methods are compiled oddly:

<blockquote><pre>class Base {
  static void foo() {}
}

class Derived extends Base {
}</pre></blockquote>

    The bytecode for a call to <code>Derived.foo()</code> is "<code>void Derived.foo()</code>,"
    not "<code>void Base.foo()</code>."  The VM knows to look for the method first in <code>Derived</code>
    and then in <code>Base</code>.
  </li>
</ol>

<p>
    So:
    The compiler can see that <code>Collection&lt;HashSet&lt;Object&gt;&gt;</code> does not
    implement <code>Comparable</code>.  Thus, it chooses the more general "inherited" version <code>&lt;E&gt;
    print(Iterable&lt;E&gt;)</code> over the restricted version <code>&lt;E extends Comparable&lt;? super E&gt;&gt;
    print(Iterable&lt;E&gt;)</code>.  Nevertheless, per point #2 above, the bytecode it produces still reads "<code>void
    SortedPrinter.print(Iterable)</code>."
</p>

<p>
    The VM sees "<code>void SortedPrinter.print(Iterable)</code>" and begins its search for <code>void print(Iterable)</code> in
    <code>SortedPrinter</code>.  <code>SortedPrinter</code> has exactly such a method.  The fact that it requires
    its input to be <code>Comparable</code> is unavailable at runtime.  The VM chooses that method.
</p>

<p>
    Thus, all three "<code>SortedPrinter.print()</code>" calls <strong>end up really calling
    <code>SortedPrinter.print()</code>, even though the compiler/IDE believes it is
    compiling a call to <code>Printer.print()</code></strong> in the HashSet case.  At runtime,
    <code>SortedPrinter.print()</code> implicitly casts each element of its input to
    <code>Comparable</code> ("<code>for (E e : input)</code>"), and the failure to cast <code>HashSet</code> gives
    us a <code>ClassCastException</code>.
</p>

    </div>
    <xhtml:h4>More Fun</xhtml:h4>
    <div>

    <p>This is a hole in the type system, but the fun doesn't stop there.  By adding method X, I can cause a call to method Y to become a call to method Z:</p>

<blockquote><pre>import java.util.HashSet;
import static java.util.Collections.singleton;

class Base {
  static &lt;E&gt; Object count(Iterable&lt;E&gt; input) {
    System.out.println("Base");
    int count = 0;
    for (E e : input) {
      count++;
    }
    return count;
  }
}

class Sub extends Base {
/*  static &lt;E&gt; Integer count(Iterable&lt;E&gt; input) {
    System.out.println("Sub");
    int count = 0;
    for (E e : input) {
      count++;
    }
    return count;
  }*/
}

class Subsub extends Sub {
  static &lt;E extends Comparable&lt;? super E&gt;&gt; Integer count(Iterable&lt;E&gt; input) {
    System.out.println("Subsub");
    int count = 0;
    for (E e : input) {
      count++;
    }
    return count;
  }
}

class Caller2 {
  public static void main(String[] args) {
    Subsub.count(singleton(1));
    Subsub.count(singleton(null));
    Subsub.count(singleton(new HashSet&lt;Object&gt;()));
  }
}</pre></blockquote>

<p>With <code>Sub.count()</code> commented out, we get:</p>

<blockquote><pre>Subsub
Base
Base</pre></blockquote>

<p>With <code>Sub.count()</code> restored, we get:</p>

<blockquote><pre>Subsub
Subsub
Subsub
&lt;the ClassCastException&gt;</pre></blockquote>

<p>Notice that <strong>in no case is <code>Sub.count()</code> itself called.  Its mere presence affects the behavior of the program.</strong></p>

<p>Why? The existence of <code>Sub.count()</code> makes the compiler write "<code>Integer Subsub.count()</code>" instead of "<code>Object Subsub.count()</code>."  At runtime, the former resolves to <code>Subsub.count()</code>; the latter, to <code>Base.count()</code>.</p>

<p>If you do want <code>Sub.count()</code> to be called, you must change its return type to <code>Object</code>.  Then we get:</p>

<blockquote><pre>Subsub
Sub
Sub</pre></blockquote>

<p>Changing the method's return type again changes which method is called.  The first method the compiler finds when looking for an appropriate <code>Subsub.count()</code> is still <code>Sub.count()</code>, but now it writes "<code>Object Subsub.count()</code>" instead of "<code>Integer Subsub.count()</code>."  At runtime, the former resolves to the appropriate method.</p>

    </div>

    <xhtml:h4>Lessons</xhtml:h4>
    <div>

    <p>First, the controversial part: When a compiler identifies a call to method X, it should produce code that calls method X, not hypothetical method Y.</p>

    <p>Second, programmers should generally avoid "overriding" static methods, most of all when type parameters are involved.  <code>&lt;E extends Comparable&lt;? super E&gt;&gt; ImmutableSortedSet.of(E)</code> and its superclass's <code>&lt;E&gt; ImmutableSet.of(E)</code> do not play nicely together.  Expect some gymnastics in <a href="http://google-collections.googlecode.com/svn/trunk/src/com/google/common/collect/ImmutableSortedSet.java">the <code>ImmutableSortedSet</code> code</a> next release.</p>

    </div>

    </div>

  </div>
      </div>
    </content>
  </entry></feed>
