title: Why isn't java typesafe when inferring array types?
body: <p>I was playing around with generics and found that, to my surprise, the following code compiles:</p>
  
  <pre><code>class A {}
  class B extends A {}
  
  class Generic&lt;T&gt; {
      private T instance;
      public Generic(T instance) {
          this.instance = instance;
      }
      public T get(){ return instance; }
  }
  
  public class Main {
      public static void main(String[] args) {
          fArray(new B[1], new Generic&lt;A&gt;(new A())); // &lt;-- No error here
      }
  
      public static &lt;T&gt; void fArray(T[] a, Generic&lt;? extends T&gt; b) {
          a[0] = b.get();
      }
  }
  </code></pre>
  
  <p>I would expect <code>T</code> to be inferred to <code>B</code>. <code>A</code> does not extend <code>B</code>. So why doesn't the compiler complain about it?</p>
  
  <p><code>T</code> seems to be inferred to <code>Object</code>, since I can pass a <code>Generic&lt;Object&gt;</code> as well.</p>
  
  <p>Moreover, <strong>when actually running the code</strong>, it throws an <code>ArrayStoreException</code> on the <code>a[0] = b.get();</code> line.</p>
  
  <p>I'm not using any raw generic types. I feel like this exception could have been avoided with a compile time error, or at least a warning, if <code>T</code> was actually inferred to be <code>B</code>.</p>
  
  <hr>
  
  <p>When further testing with the <code>List&lt;...&gt;</code> equivalent:</p>
  
  <pre><code>public static void main(String[] args) {
      fList(new ArrayList&lt;B&gt;(), new Generic&lt;A&gt;(new A())); // &lt;-- Error, as expected
  }
  
  public static &lt;T&gt; void fList(List&lt;T&gt; a, Generic&lt;? extends T&gt; b) {
      a.add(b.get());
  }
  </code></pre>
  
  <p>This does produce and error:</p>
  
  <pre><code>The method fList(List&lt;T&gt;, Generic&lt;? extends T&gt;) in the type Main is not applicable for the arguments (ArrayList&lt;B&gt;, Generic&lt;A&gt;)
  </code></pre>
  
  <p>As does the more generic case:</p>
  
  <pre><code>public static &lt;T&gt; void fList(List&lt;? extends T&gt; a, Generic&lt;? extends T&gt; b) {
      a.add(b.get()); // &lt;-- Error here
  }
  </code></pre>
  
  <p>The compiler correctly recognizes that the first <code>?</code> might be further down the inheritance hierarchy than the second <code>?</code>.</p>
  
  <p>e.g. If the first <code>?</code> were <code>B</code> and the second <code>?</code> were <code>A</code> then this isn't type safe.</p>
  
  <hr>
  
  <p>So why doesn't the first example produce a similar compiler error? Is it just an oversight? Or is there a technical limitation?</p>
  
  <p>The only way I could produce an error is by explicitly providing a type:</p>
  
  <pre><code>Main.&lt;B&gt;fArray(new B[1], new Generic&lt;A&gt;(new A())); // &lt;-- Not applicable
  </code></pre>
  
  <hr>
  
  <p>I didn't really find anything through my own research, except for <a href="http://c2.com/cgi/wiki?JavaArraysBreakTypeSafety" rel="nofollow noreferrer">this article</a> from 2005 (before generics), which talks about the dangers of array covariance.</p>
  
  <p>Array covariance seems to hint towards an explanation, but I can't think of one.</p>
  
  <hr>
  
  <p>Current jdk is 1.8.0.0_91</p>