Note that there are some explanatory texts on larger screens.

plurals
  1. POJava generic methods in generics classes
    primarykey
    data
    text
    <p>If you create a generic class in Java (the class has generic type parameters), can you use generic methods (the method takes generic type parameters)?</p> <p>Consider the following example:</p> <pre><code>public class MyClass { public &lt;K&gt; K doSomething(K k){ return k; } } public class MyGenericClass&lt;T&gt; { public &lt;K&gt; K doSomething(K k){ return k; } public &lt;K&gt; List&lt;K&gt; makeSingletonList(K k){ return Collections.singletonList(k); } } </code></pre> <p>As you would expect with a generic method, I can call <code>doSomething(K)</code> on instances of <code>MyClass</code> with any object:</p> <pre><code>MyClass clazz = new MyClass(); String string = clazz.doSomething("String"); Integer integer = clazz.doSomething(1); </code></pre> <p>However, if I try to use instances of <code>MyGenericClass</code> <em>without</em> specifying a generic type, I calling <code>doSomething(K)</code> returns an <code>Object</code>, regardless of what <code>K</code> was passed in:</p> <pre><code>MyGenericClass untyped = new MyGenericClass(); // this doesn't compile - "Incompatible types. Required: String, Found: Object" String string = untyped.doSomething("String"); </code></pre> <p>Oddly, it will compile if the return type is a generic class - e.g. <code>List&lt;K&gt;</code> (Actually, this can be explained - see answer below):</p> <pre><code>MyGenericClass untyped = new MyGenericClass(); List&lt;String&gt; list = untyped.makeSingletonList("String"); // this compiles </code></pre> <p>Also, it will compile if the generic class is typed, even if only with wildcards:</p> <pre><code>MyGenericClass&lt;?&gt; wildcard = new MyGenericClass(); String string = wildcard.doSomething("String"); // this compiles </code></pre> <ul> <li><p>Is there a good reason why calling a generic method in an untyped generic class shouldn't work?</p></li> <li><p>Is there some clever trick relating to generic classes and generic methods that I am missing?</p></li> </ul> <p>EDIT:</p> <p>To clarify, I would expect an untyped or raw-typed generic class not to honour the generic class's type parameters (because they haven't been provided). However, it's not clear to my why an untyped or raw-typed generic class would mean that generic methods are not honoured. </p> <p>It transpires that this issue has already been raised on SO, c.f. <a href="https://stackoverflow.com/questions/11007723/combining-raw-types-and-generic-methods">this question</a>. The answers to this explain that when a class is untyped / in its raw-form, <em>all</em> generics are removed from the class - including typing of generic methods.</p> <p>However, there isn't really an explanation as to why this is the case. So allow me to clarify my question:</p> <ul> <li>Why does Java remove generic method typing on untyped or raw-type generic classes? Is there a good reason for this, or was it just an oversight?</li> </ul> <p>EDIT - discussion of JLS:</p> <p>It has been suggested (in answer to the previous SO question and to this question) that this is treated in <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.8" rel="nofollow noreferrer">JLS 4.8</a>, which states:</p> <blockquote> <p>The type of a constructor (§8.8), instance method (§8.4, §9.4), or non-static field (§8.3) M of a raw type C that is not inherited from its superclasses or superinterfaces is the raw type that corresponds to the erasure of its type in the generic declaration corresponding to C. </p> </blockquote> <p>It is clear to me how this relates to an untyped class - the class generic types are replaced with the erasure types. If the class generics are bound, then the erasure type corresponds to those bounds. If the they are not bound, then the erasure type is Object - e.g. </p> <pre><code>// unbound class types public class MyGenericClass&lt;T&gt; { public T doSomething(T t) { return t; } } MyGenericClass untyped = new MyGenericClass(); Object t = untyped.doSomething("String"); // bound class types public class MyBoundedGenericClass&lt;T extends Number&gt; { public T doSomething(T t) { return t; } } MyBoundedGenericClass bounded = new MyBoundedGenericClass(); Object t1 = bounded.doSomething("String"); // does not compile Number t2 = bounded.doSomething(1); // does compile </code></pre> <p>Whilst generic methods are instance methods, it is not clear to me that JLS 4.8 applies to generic methods. The generic method's type (<code>&lt;K&gt;</code> in earlier example) is not untyped, as it's type is determined by the method parameters - only the class is untyped / raw-typed.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload