{"id":119,"date":"2009-08-26T00:49:11","date_gmt":"2009-08-25T13:49:11","guid":{"rendered":"http:\/\/christopherowen.id.au\/blog\/?p=119"},"modified":"2020-01-19T10:23:49","modified_gmt":"2020-01-18T23:23:49","slug":"java-developers-have-99-problems","status":"publish","type":"post","link":"https:\/\/christopherowen.au\/blog\/2009\/08\/26\/java-developers-have-99-problems\/","title":{"rendered":"Java developers have 99 problems&#8230;"},"content":{"rendered":"\n<p>&#8230; but this ain&#8217;t one.<\/p>\n\n\n\n<p>Today Yahuda Katz posted his <a href=\"http:\/\/yehudakatz.com\/2009\/08\/24\/my-10-favorite-things-about-the-ruby-language\/\">10 favourite things about the ruby language<\/a>. His list certainly reflects most of the things I find very appealing about the language. The sixth item highlights Ruby&#8217;s excellent support for blocks and lambdas and an argument is mounted that when performing file operations in languages without them, programmers are <q>forced to use an inline \u201censure\u201d block every in the same lexical scope that they originally opened the file in, to ensure that the resource is closed.<\/q> As is often the case the comparison is made to Java, but as any seasoned Java developer will tell you (and this point has probably be made many, many times) it just isn&#8217;t true. Java supports a safer and comparable idiom via the anonymous inner class.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p>The example given is a very succinct Ruby method to print out the lines of a text file. Ruby&#8217;s <kbd>File.open<\/kbd> ensures the file is properly closed after the block has completed, normally or otherwise:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"Ruby\" data-shcb-language-slug=\"ruby\"><span><code class=\"hljs language-ruby\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">run<\/span><span class=\"hljs-params\">(input)<\/span><\/span>\n  File.open(input, <span class=\"hljs-string\">\"r\"<\/span>) <span class=\"hljs-keyword\">do<\/span> <span class=\"hljs-params\">|f|<\/span>\n    f.each_line {<span class=\"hljs-params\">|line|<\/span> puts line }\n  <span class=\"hljs-keyword\">end<\/span>\n<span class=\"hljs-keyword\">end<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Ruby<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">ruby<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The Java version listed does the same but, predictably, is far more verbose and laborious:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">void<\/span> run(<span class=\"hljs-built_in\">String<\/span> <span class=\"hljs-keyword\">in<\/span>) \nthrows FileNotFoundException {\n  File input = <span class=\"hljs-keyword\">new<\/span> File(<span class=\"hljs-keyword\">in<\/span>);\n  <span class=\"hljs-built_in\">String<\/span> line; Scanner reader = <span class=\"hljs-literal\">null<\/span>;\n  <span class=\"hljs-keyword\">try<\/span> {\n    reader = <span class=\"hljs-keyword\">new<\/span> Scanner(input);\n    <span class=\"hljs-keyword\">while<\/span>(reader.hasNextLine()) {\n      System.out.println(reader.nextLine());\n    }\n  } <span class=\"hljs-keyword\">finally<\/span> { reader.close(); }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>However no Java developer that values their sanity is ever going to sprinkle this pattern through their code base any time they want to use a File and ensure that it is closed properly. Here&#8217;s what they are going to use instead:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">interface<\/span> <span class=\"hljs-title\">Processor<\/span> <\/span>{\n  void process(T target);\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">import<\/span> java.io.*;\n<span class=\"hljs-keyword\">import<\/span> java.util.Scanner;\n\npublic <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">FileSlurper<\/span> <\/span>{\n \n  public <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">void<\/span> slurp(<span class=\"hljs-built_in\">String<\/span> fileName, Processor processor) \n    throws FileNotFoundException {\n\n    File input = <span class=\"hljs-keyword\">new<\/span> File(fileName);\n    Scanner reader = <span class=\"hljs-literal\">null<\/span>;\n    <span class=\"hljs-keyword\">try<\/span> {\n      reader = <span class=\"hljs-keyword\">new<\/span> Scanner(input);\n      processor.process(reader);\n    }\n    <span class=\"hljs-keyword\">finally<\/span> {\n      reader.close();\n    }\n  }\n\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Once that infrastructure is in place, the Java implementation of the example becomes:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">FileSlurper.slurp(input, <span class=\"hljs-keyword\">new<\/span> Processor() {\n  public <span class=\"hljs-keyword\">void<\/span> process(Scanner reader) {\n    <span class=\"hljs-keyword\">while<\/span>(reader.hasNextLine())\n      System.out.println(reader.nextLine());\n  }\n});<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>No one can argue that this is as pretty or convenient as the Ruby version, but it does ensure that file opening and closing is handled correctly without any effort from the client code. The code in the anonymous inner class can even access variables in the current lexical context, as with the Ruby block, with the caveat that they must be declared <kbd>final<\/kbd> (not quite a lexical closure!). This pattern, in conjunction with the <kbd>Processor<\/kbd> interface may be used any time there is a need for similar resource acquisition and clean\u2013up procedures, as might be the case for locks or database connections.<\/p>\n\n\n\n<p>Lambdas and blocks are very useful constructs, and the anonymous inner class can act as an acceptable, if far from ideal, analogue. What an anonymous inner class can&#8217;t do is act as a co\u2013routine; this is a truly powerful feature of Ruby&#8217;s blocks and associated method invocation features that Java can&#8217;t directly compete with.<\/p>\n\n\n\n<p>One thing&#8217;s for certain: the Ruby community won&#8217;t win over Java developers by giving examples of deficiencies where none exist.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Java developers have many problems but safe resource acquisition and release isn&#8217;t one.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"activitypub_content_warning":"","activitypub_content_visibility":"","activitypub_max_image_attachments":4,"activitypub_interaction_policy_quote":"","activitypub_status":"","footnotes":""},"categories":[19],"tags":[],"class_list":["post-119","post","type-post","status-publish","format-standard","hentry","category-programming"],"_links":{"self":[{"href":"https:\/\/christopherowen.au\/blog\/wp-json\/wp\/v2\/posts\/119","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/christopherowen.au\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/christopherowen.au\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/christopherowen.au\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/christopherowen.au\/blog\/wp-json\/wp\/v2\/comments?post=119"}],"version-history":[{"count":4,"href":"https:\/\/christopherowen.au\/blog\/wp-json\/wp\/v2\/posts\/119\/revisions"}],"predecessor-version":[{"id":331,"href":"https:\/\/christopherowen.au\/blog\/wp-json\/wp\/v2\/posts\/119\/revisions\/331"}],"wp:attachment":[{"href":"https:\/\/christopherowen.au\/blog\/wp-json\/wp\/v2\/media?parent=119"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/christopherowen.au\/blog\/wp-json\/wp\/v2\/categories?post=119"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/christopherowen.au\/blog\/wp-json\/wp\/v2\/tags?post=119"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}