{"id":1017,"date":"2023-11-05T02:12:46","date_gmt":"2023-11-05T02:12:46","guid":{"rendered":"https:\/\/alphastar.net.au\/weblog\/?p=1017"},"modified":"2024-10-21T12:31:00","modified_gmt":"2024-10-21T12:31:00","slug":"java-generics","status":"publish","type":"post","link":"https:\/\/alphastar.net.au\/weblog\/2023\/11\/05\/java-generics\/","title":{"rendered":"Java Generics"},"content":{"rendered":"<p>Part of my job as a Java developer I need to navigate some areas of the code base that I&#8217;m not as familiar with. Generics is one of the more arcane areas of Java. I decided to go head first into documenting my journey in learning the application of generics.<\/p>\n<h2>Introduction<\/h2>\n<p><span class=\"il\">Generics<\/span>\u00a0are a Java feature available since Java 1.5<u><\/u><u><\/u><\/p>\n<p>It allows for passing type information to allow for better code reuse.<u><\/u><u><\/u><\/p>\n<p>Classic example to start things off easy:<u><\/u><u><\/u><\/p>\n<p>ArrayList&lt;T&gt; mandates that the class may use elements of some particular type T. Whether that be String, Integer, Address (for example) etc.<u><\/u><u><\/u><\/p>\n<p>The usefulness comes in that if we try to add an object of an incorrect type, the code will not compile.\u00a0<span class=\"il\">Generics<\/span>\u00a0add compile time safety<u><\/u><u><\/u><\/p>\n<p><u><\/u>\u00a0<u><\/u><\/p>\n<p>T is the placeholder for the type information. It may be useful to circumvent this convention and make the typeholder name more explicit, for instance TRecord.<u><\/u><\/p>\n<p>? indicates some unknown but specific type. Java type inference will work out the ? (known as a capture) by trying to bind this with the type of some known value.<u><\/u><u><\/u><\/p>\n<p>It may try to work this out from a parameter passed in for instance.<u><\/u><u><\/u><\/p>\n<p><u><\/u>\u00a0<u><\/u><\/p>\n<p>Simple example for a class<u><\/u><u><\/u><\/p>\n<p>public class MyClass&lt;T extends Number&gt;<u><\/u><u><\/u><\/p>\n<p><u><\/u>\u00a0<u><\/u><\/p>\n<p>Simple example at method level. Note that the\u00a0<span class=\"il\">generic<\/span>\u00a0type should appear BEFORE the return type:<u><\/u><u><\/u><\/p>\n<p><u><\/u>\u00a0<u><\/u><\/p>\n<pre>public static &lt;T extends Recordable&gt; void asyncProcessQuery(...) {\r\n...\r\n}<u><\/u><u><\/u><\/pre>\n<p><u><\/u>\u00a0<u><\/u><\/p>\n<p><u>Ranges<\/u><u><\/u><u><\/u><\/p>\n<p>super \/ extends specify acceptable types in context of a particular hierarchy<u><\/u><u><\/u><\/p>\n<p>For instance if we have the hierarchy (with some made up types for ease of illustration):<u><\/u><u><\/u><\/p>\n<p>Object \u2192 Number \u2192 Integer \u2192 AwesomeInteger \u2192 SuperAwesomeInteger<u><\/u><u><\/u><\/p>\n<p>&#8220;super AwesomeInteger&#8221; is a lower bound: It contains the types: Object, Number, Integer, AwesomeInteger (it contains itself)<u><\/u><u><\/u><\/p>\n<p>&#8220;extends Integer&#8221; is an upper bound: It contains the types Integer (always includes itself), AwesomeInteger, SuperAwesomeInteger<u><\/u><u><\/u><\/p>\n<p><u><\/u>\u00a0<u><\/u><\/p>\n<p>Lets take an example using List&lt;? extends Integer&gt; someList = new ArrayList&lt;&gt;();<u><\/u><u><\/u><\/p>\n<p>To some (and it included me at one stage), this appears to say that an ArrayList can contain any combination of elements, as long as it is Integer or beyond. THIS IS WRONG!<u><\/u><u><\/u><\/p>\n<p>You cannot add an Integer to this list, nor can you add a SuperAwesomeInteger. For reasons that will be explained. You cannot add\u00a0<em>anything\u00a0<\/em>to it!<u><\/u><u><\/u><\/p>\n<p>What this is saying, is that I can assign a List that is of a particular known type that starts from Integer or a subclass of<u><\/u><u><\/u><\/p>\n<p><strong>List&lt;? extends Integer&gt;<\/strong>\u00a0someList = new ArrayList&lt;Integer&gt;();<u><\/u><u><\/u><\/p>\n<p><strong>List&lt;? extends Integer&gt;<\/strong>\u00a0anotherList = new ArrayList&lt;AwesomeInteger&gt;();<u><\/u><u><\/u><\/p>\n<p><u><\/u>\u00a0<u><\/u><\/p>\n<p>Contrarily with super, the semantics are reversed<u><\/u><u><\/u><\/p>\n<p><u><\/u>\u00a0<u><\/u><\/p>\n<p><strong>List&lt;? super Integer&gt;<\/strong>\u00a0someList = new ArrayList&lt;Number&gt;();<u><\/u><u><\/u><\/p>\n<p>is acceptable.<u><\/u><u><\/u><\/p>\n<h1 id=\"m_-891722283473399499NotesonGenerics-PECS\">PECS<u><\/u><u><\/u><\/h1>\n<p>This is a mnemonic devised by Josh Block (the author of\u00a0<span class=\"il\">Generics<\/span>)<u><\/u><u><\/u><\/p>\n<p>To boil it down simply<u><\/u><u><\/u><\/p>\n<p>if you want to SET something, you use super<u><\/u><u><\/u><\/p>\n<p>If you want to READ something, you use extends<u><\/u><u><\/u><\/p>\n<p>If you want to both SET and READ, then use the exact type.<u><\/u><u><\/u><\/p>\n<p><u><\/u>\u00a0<u><\/u><\/p>\n<p>For instance, if we have\u00a0<strong>List&lt;? super Integer&gt;\u00a0<\/strong>list = new ArrayList&lt;&gt;();<u><\/u><u><\/u><\/p>\n<p>What values can we add to it?<u><\/u><u><\/u><\/p>\n<p>Tempting to think that we can add Integers, Number, and Objects, as that&#8217;s the types defined within the super clause. No we can&#8217;t do that.<u><\/u><u><\/u><\/p>\n<p>We can add Integer, AwesomeInteger and any further subclass.<u><\/u><u><\/u><\/p>\n<p>The reason being, we\u00a0<em>cannot know\u00a0<\/em>which type this List will be. Hence we must use an object that would satisfy\u00a0<em>any of them<\/em>.<u><\/u><u><\/u><\/p>\n<p>If we plug in a value of SuperAwesomeInteger, AwesomeInteger or Integer, then this will be fine, as each of these types can be assigned to a list of List&lt;Object&gt;, List&lt;Number&gt;, List&lt;Integer&gt;<u><\/u><u><\/u><\/p>\n<p>So, again if we want to\u00a0<strong><i>write\/add\u00a0<\/i><\/strong>something, we use super<u><\/u><u><\/u><\/p>\n<p><u><\/u>\u00a0<u><\/u><\/p>\n<p>On the flip side when we use &#8220;extends&#8221; we cannot write to it but we can\u00a0<strong><i>read\u00a0<\/i><\/strong>from it.<u><\/u><u><\/u><\/p>\n<p>For instance\u00a0<strong>List&lt;? extends Integer&gt;<\/strong><u><\/u><u><\/u><\/p>\n<p>We can assign a list of List&lt;Integer&gt;, List&lt;AwesomeInteger&gt; etc. to the above list.<u><\/u><u><\/u><\/p>\n<p>But given the List&lt;? extends Integer&gt; declaration, we cannot know which List will be assigned. Only that some list that is a subclass of Integer will be, e.g. we could assign List&lt;SuperAwesomeInteger&gt; but not List&lt;Number&gt; (as it appears below our bound)<u><\/u><u><\/u><\/p>\n<p><u><\/u>\u00a0<u><\/u><\/p>\n<p>With this in mind, what we know is that whatever the List is, we can READ from it. However we can&#8217;t necessarily read it as a SuperAwesomeInteger, as the list might actually be pointing to Integer (which won&#8217;t have the attributes of a SuperAwesomeInteger)<u><\/u><u><\/u><\/p>\n<p>What we do know is that we can MINIMALLY read any of these objects as Integer (or Number or Object)<u><\/u><u><\/u><\/p>\n<p><u><\/u>\u00a0<u><\/u><\/p>\n<p>for (Integer i : myList) {<u><\/u><u><\/u><\/p>\n<p>system.out.println(i.sigNum()<wbr \/>) \/\/ some method on Integer<u><\/u><u><\/u><\/p>\n<p>}<u><\/u><u><\/u><\/p>\n<p><u><\/u>\u00a0<u><\/u><\/p>\n<p>A note: &#8220;extends&#8221; in the context of\u00a0<span class=\"il\">Generic<\/span>\u00a0type constraints can either mean extends in the case of classes, but should be read as &#8216;implements&#8217; when an interface is present, as we aren&#8217;t really extending an interface but checking that some type implements an interface.<u><\/u><u><\/u><\/p>\n<p>The rule for using ampersand here is that the first type can be concrete or an interface. Any further types (i.e. after the &amp;) must be interfaces.<u><\/u><u><\/u><\/p>\n<h2 id=\"m_-891722283473399499NotesonGenerics-Thistableshowswhereyoucanvalidlyuseextends\/super\">This table shows where you can validly use extends \/ super<u><\/u><u><\/u><\/h2>\n<p><u><\/u>\u00a0<u><\/u><\/p>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td valign=\"top\"><strong>T extends Something<\/strong><u><\/u><u><\/u><\/td>\n<td valign=\"top\"><strong>? extends \/ super Something<\/strong><u><\/u><u><\/u><\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">Used in class as a\u00a0<strong>declaration<\/strong><u><\/u><u><\/u><\/p>\n<p>Ex:<u><\/u><u><\/u><\/p>\n<p>Class List&lt;T&gt;, class List&lt;T extends Number&gt;<u><\/u><u><\/u><\/p>\n<p>First style is more common in Java code, it is implicitly T extends Object<u><\/u><u><\/u><\/td>\n<td valign=\"top\"><strong>Usage\u00a0<\/strong>of class, ex<u><\/u><u><\/u><\/p>\n<p>List x = new ArrayList&lt;? Extends Number&gt;<u><\/u><u><\/u><\/p>\n<p>Specifies unknown but specific type<u><\/u><u><\/u><\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">Used in LHS (i.e. before the return type) of method as a\u00a0<strong>declaration\u00a0<\/strong>of the method.<u><\/u><u><\/u><\/p>\n<p>Ex:<u><\/u><u><\/u><\/p>\n<p>static &lt;T extends Number&gt; void gPrintA(List&lt;T&gt; l)<u><\/u><u><\/u><\/td>\n<td valign=\"top\">Method level.\u00a0<strong>Usage<\/strong><u><\/u><u><\/u><\/p>\n<p>Ex:<u><\/u><u><\/u><\/p>\n<p>void gPrint(List&lt;? extends Number&gt; l)<u><\/u><u><\/u><\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">Cannot be used when invoking class.<u><\/u><u><\/u><\/p>\n<p><s>List a = new ArrayList&lt;T extends Number&gt;<\/s><u><\/u><u><\/u><\/p>\n<p>(Can only use ? extends\/super)<u><\/u><u><\/u><\/td>\n<td valign=\"top\">Cannot be used in class definition<u><\/u><u><\/u><\/p>\n<p><s>Class Brother&lt;? Extends Number&gt;<\/s><u><\/u><u><\/u><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<p><strong>Captures<\/strong><u><\/u><u><\/u><\/p>\n<p>&nbsp;<\/p>\n<p>? have to be \u201ccaptured\u201d i.e. the compiler has to know what each ? is bound to. It can be a T type.<u><\/u><u><\/u><\/p>\n<p>&nbsp;<\/p>\n<p>Example helper<u><\/u><u><\/u><\/p>\n<p>&nbsp;<\/p>\n<p>public static void reverse(List&lt;?&gt; list)\u00a0{ rev(list); }<u><\/u><u><\/u><\/p>\n<p>private static\u00a0&lt;T&gt;\u00a0void rev(List&lt;T&gt; list)\u00a0{<u><\/u><u><\/u><\/p>\n<p>List&lt;T&gt; tmp =\u00a0new ArrayList&lt;T&gt;(list);<u><\/u><u><\/u><\/p>\n<p>for\u00a0(int i = 0; i &lt; list.size(); i++) {<u><\/u><u><\/u><\/p>\n<p>list.set(i, tmp.get(list.size() &#8211; i &#8211;\u00a01));<u><\/u><u><\/u><\/p>\n<p>}<u><\/u><u><\/u><\/p>\n<p>}<u><\/u><u><\/u><\/p>\n<p><u><\/u>\u00a0<u><\/u><\/p>\n<h2 id=\"m_-891722283473399499NotesonGenerics-Furtherreading\">Further reading<u><\/u><u><\/u><\/h2>\n<p>super and extends\u00a0<a href=\"https:\/\/stackoverflow.com\/questions\/4343202\/difference-between-super-t-and-extends-t-in-java\" target=\"_blank\" rel=\"noopener\" data-saferedirecturl=\"https:\/\/www.google.com\/url?q=https:\/\/stackoverflow.com\/questions\/4343202\/difference-between-super-t-and-extends-t-in-java&amp;source=gmail&amp;ust=1699236255104000&amp;usg=AOvVaw0Vx_qp5VII9CU9_3cnc2eU\">https:\/\/stackoverflow.<wbr \/>com\/questions\/4343202\/<wbr \/>difference-between-super-t-<wbr \/>and-extends-t-in-java<\/a><u><\/u><u><\/u><\/p>\n<p>Java ? capture\u00a0<a href=\"https:\/\/docs.oracle.com\/javase\/tutorial\/java\/generics\/capture.html\" target=\"_blank\" rel=\"noopener\" data-saferedirecturl=\"https:\/\/www.google.com\/url?q=https:\/\/docs.oracle.com\/javase\/tutorial\/java\/generics\/capture.html&amp;source=gmail&amp;ust=1699236255104000&amp;usg=AOvVaw2EQzIWywOy8lsVneCjcZMW\">https:\/\/docs.oracle.<wbr \/>com\/javase\/tutorial\/java\/<wbr \/><span class=\"il\">generics<\/span>\/capture.html<\/a><u><\/u><u><\/u><\/p>\n<p>Curiously recursive template pattern (used in builders)\u00a0<a href=\"https:\/\/nuah.livejournal.com\/328187.html\" target=\"_blank\" rel=\"noopener\" data-saferedirecturl=\"https:\/\/www.google.com\/url?q=https:\/\/nuah.livejournal.com\/328187.html&amp;source=gmail&amp;ust=1699236255104000&amp;usg=AOvVaw09BKX_ABbKOalUQKrZ8f8A\">https:\/\/nuah.<wbr \/>livejournal.com\/328187.html<\/a><u><\/u><u><\/u><\/p>\n<p>PECS\u00a0<a href=\"https:\/\/howtodoinjava.com\/java\/generics\/java-generics-what-is-pecs-producer-extends-consumer-super\/\" target=\"_blank\" rel=\"noopener\" data-saferedirecturl=\"https:\/\/www.google.com\/url?q=https:\/\/howtodoinjava.com\/java\/generics\/java-generics-what-is-pecs-producer-extends-consumer-super\/&amp;source=gmail&amp;ust=1699236255104000&amp;usg=AOvVaw1dH04eKs95q9FP5RSPdtYK\">https:\/\/howtodoinjava.<wbr \/>com\/java\/<span class=\"il\">generics<\/span>\/java-<wbr \/><span class=\"il\">generics<\/span>-what-is-pecs-<wbr \/>producer-extends-consumer-<wbr \/>super\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Part of my job as a Java developer I need to navigate some areas of the code base that I&#8217;m not as familiar with. Generics is one of the more&#8230; <\/p>\n","protected":false},"author":1,"featured_media":1019,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-1017","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-coding"],"_links":{"self":[{"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/posts\/1017","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/comments?post=1017"}],"version-history":[{"count":2,"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/posts\/1017\/revisions"}],"predecessor-version":[{"id":1020,"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/posts\/1017\/revisions\/1020"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/media\/1019"}],"wp:attachment":[{"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/media?parent=1017"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/categories?post=1017"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/tags?post=1017"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}