{"id":1372,"date":"2010-11-24T23:08:19","date_gmt":"2010-11-24T22:08:19","guid":{"rendered":"http:\/\/www.gamlor.info\/wordpress\/?p=1372"},"modified":"2021-07-03T13:26:54","modified_gmt":"2021-07-03T12:26:54","slug":"magic-cast-method-in-java","status":"publish","type":"post","link":"https:\/\/www.gamlor.info\/wordpress\/2010\/11\/magic-cast-method-in-java\/","title":{"rendered":"Magic Cast Method in Java"},"content":{"rendered":"<p>Since Java introduced generics the type declarations got at lot longer. This is especially annoying when an API forces you to cast objects, like the reflection-API, the <a href=\"http:\/\/db.apache.org\/jdo\/api30\/apidocs\/javax\/jdo\/Query.html#execute()\">JDO-API <\/a>, etc. There are plenty of APIs which requires such casts. Those casts force you to write the (obvious) type twice, for the type-declaration and the cast.<br \/>\n<script src=\"https:\/\/gist.github.com\/714140.js?file=OhNo.its.JDO.java\"><\/script><noscript><pre><code class=\"language-java java\">PersistenceManager persistenceManager = \/\/ get persistence \nCollection&lt;Book&gt; allBooks = (Collection&lt;Book&gt;) persistenceManager.newQuery(Book.class).execute();<\/code><\/pre><\/noscript><\/p>\n<div id=\"attachment_1382\" style=\"width: 310px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2010\/11\/cast-magic-omat.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-1382\" src=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2010\/11\/cast-magic-omat-300x240.png\" alt=\"Magic Java Casts\" title=\"cast-magic-omat\" class=\"size-medium wp-image-1382\" width=\"300\" height=\"240\" srcset=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2010\/11\/cast-magic-omat-300x240.png 300w, https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2010\/11\/cast-magic-omat.png 1024w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><p id=\"caption-attachment-1382\" class=\"wp-caption-text\">Magic Java Casts<\/p><\/div>\n<h2>Generic Trickery<\/h2>\n<p>We know that for methods the generic arguments can be inferred. I already demonstrated that this can be used to <a href=\"?p=1020\">rethrow checked exceptions without wrapping it<\/a>, which has become one of my favorite Java utility methods. So maybe we can create something similar for casts? Well yes, it\u2019s possible. In order to do so we just define a static cast-method. The return type and the argument type are generic. Since both are inferred by the compiler, we just introduced a \u2018cast\u2019 which automatically casts to the expected type.<br \/>\n<script src=\"https:\/\/gist.github.com\/714140.js?file=CastUtility.java\"><\/script><noscript><pre><code class=\"language-java java\">public class JavaLangUtils {\n    private JavaLangUtils(){\n    }\n\n    public static &lt;TSource,TTarget&gt; TTarget cast(TSource toCast){\n        return (TTarget) toCast;\n    }\n}<\/code><\/pre><\/noscript><br \/>\nA few examples of the usage<br \/>\n<script src=\"https:\/\/gist.github.com\/714140.js?file=UseIt.java\"><\/script><noscript><pre><code class=\"language-java java\">\/\/ the cast now just casts to the type we write on the left\n\/\/ the type is inferred\nMap&lt;String, Set&lt;Book&gt;&gt; booksByTag = cast(obj);\n\n\/\/ another example:\nObject number = 1;\nInteger listOfStrings = cast(number);\n\n\/\/ JPO a bit more pleasant:\nCollection&lt;Book&gt; result = cast(persistenceManager.newQuery(Book.class).execute());<\/code><\/pre><\/noscript><\/p>\n<p>Note that this also allows impossible casts, which are usually detected by the Java compiler. Let\u2019s take a look at an example:<br \/>\n<script src=\"https:\/\/gist.github.com\/714140.js?file=LessChecks.java\"><\/script><noscript><pre><code class=\"language-java java\"> \/\/ works with our cast-method\n List&lt;String&gt; listOfStrings = cast(number);\n\n \/\/ compile error\n List&lt;String&gt; listOfStrings = (String) number;<\/code><\/pre><\/noscript><\/p>\n<p>Furthermore this only works for type declarations. If you immediately pass it to another method it doesn\u2019t work =(<br \/>\n<script src=\"https:\/\/gist.github.com\/714140.js?file=CannotPassAsMethod.java\"><\/script><noscript><pre><code class=\"language-java java\"> \/\/ Just works\n List&lt;String&gt; listOfString = cast(list);\n\n\/\/ Doesn't work\nprintAll(cast(list));<\/code><\/pre><\/noscript><\/p>\n<h2>Restrict Casting<\/h2>\n<p>Additionally we can restrict our cast method usage. We can use the co- and contra-variance declaration for generics. Even cooler we can define relations between the generic arguments. For example we can define that the cast-target has to be a sub-type in order to be casted. <script src=\"https:\/\/gist.github.com\/714140.js?file=CastWithRestrictions.java\"><\/script><noscript><pre><code class=\"language-java java\">public static &lt;TSource,TTarget extends TSource&gt; TTarget cast(TSource toCast){\n    return (TTarget) toCast;\n}<\/code><\/pre><\/noscript><br \/>\nHere&#8217;s a example where the restrictions apply <script src=\"https:\/\/gist.github.com\/714140.js?file=RestrictionsDemo.java\"><\/script><noscript><pre><code class=\"language-java java\">Set aSet = null;\n\n\/\/ works, because we cast to a sub-type\nHashSet&lt;String&gt; hashSetOfStrings = cast(aSet);\n\n\/\/ doesn't work, because we cast to a not related type\nList&lt;String&gt; listOfStrings2 = cast(aSet);<\/code><\/pre><\/noscript><\/p>\n<h2>Compiler Differences<\/h2>\n<p>With such generic trickery you might hit edge cases where the compilers disagree with each other. With this cast-method there&#8217;s a edge case when you combine the inference with auto boxing. The Java-6 javac-compiler will give a compiler error when cast something to a primitive-type. The Eclipse compiler is fine with that and works as expected. With the boxed type Integer it works just fine with both compiler.<br \/>\n<script src=\"https:\/\/gist.github.com\/714140.js?file=CompilerDifferences.java\"><\/script><noscript><pre><code class=\"language-java java\">\/\/ Works with Javac and Eclipse compiler\nInteger aInt = cast(number);\n\n\/\/ Doesn't work with the Javac compiler\n\/\/ Works fine with the Eclipse compiler\nint aInt = cast(number);<\/code><\/pre><\/noscript><\/p>\n<h2>Conclusion<\/h2>\n<p>I\u2019ve demonstrated that you can define a cast-method which infers the cast target type from its usage. However this only works in some cases, loses some compiler checks and also brings some compiler edge cases differences to the surface. So it\u2019s not really a good idea for production code.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Since Java introduced generics the type declarations got at lot longer. This is especially annoying when an API forces you to cast objects, like the reflection-API, the JDO-API , etc.&hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[15],"tags":[202,160,295],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/1372"}],"collection":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/comments?post=1372"}],"version-history":[{"count":15,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/1372\/revisions"}],"predecessor-version":[{"id":3871,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/1372\/revisions\/3871"}],"wp:attachment":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/media?parent=1372"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/categories?post=1372"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/tags?post=1372"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}