{"id":4818,"date":"2014-03-30T15:35:37","date_gmt":"2014-03-30T15:35:37","guid":{"rendered":"https:\/\/unknownerror.org\/index.php\/2014\/03\/30\/why-my-program-doesnt-show-compile-time-error-when-final-class-variable-is-not-initialized-collection-of-common-programming-errors\/"},"modified":"2022-08-30T15:42:27","modified_gmt":"2022-08-30T15:42:27","slug":"why-my-program-doesnt-show-compile-time-error-when-final-class-variable-is-not-initialized-collection-of-common-programming-errors","status":"publish","type":"post","link":"https:\/\/unknownerror.org\/index.php\/2014\/03\/30\/why-my-program-doesnt-show-compile-time-error-when-final-class-variable-is-not-initialized-collection-of-common-programming-errors\/","title":{"rendered":"Why my program doesn&#39;t show compile time error when final class variable is not initialized?-Collection of common programming errors"},"content":{"rendered":"<p>Interestingly enough, the code will compile whether or not the field is marked <code>static<\/code> &#8211; and in IntelliJ, it will complain (but compile) with the static field, and not say a word with the non-static field.<\/p>\n<p>You&#8217;re right in that JLS \u00a78.1.3.2 has certain rules regarding [static] final fields. However, there&#8217;s a few other rules around final fields that play a large role here, coming from the Java Language Specification \u00a74.12.4 &#8211; which specify the compilation semantics of a <code>final<\/code> field.<\/p>\n<p>But before we can get into that ball of wax, we need to determine what happens when we see <code>throws<\/code> &#8211; which is given to us by \u00a714.18, emphasis mine:<\/p>\n<blockquote>\n<p>A throw statement causes an exception (\u00a711) to be thrown. The result is an immediate transfer of control (\u00a711.3) <strong>that may exit multiple statements and multiple constructor, instance initializer, static initializer and field initializer evaluations, and method invocations<\/strong> until a try statement (\u00a714.20) is found that catches the thrown value. If no such try statement is found, then execution of the thread (\u00a717) that executed the throw is terminated (\u00a711.3) after invocation of the uncaughtException method for the thread group to which the thread belongs.<\/p>\n<\/blockquote>\n<p>In layman&#8217;s terms &#8211; during run-time, if we encounter a <code>throws<\/code> statement, it can interrupt the execution of the constructor (formally &#8220;completes abruptly&#8221;), causing the object to not be constructed, or constructed in an incomplete state (which could be a security hole, depending on the platform and partial completeness of the constructor).<\/p>\n<p>What the JVM expects, given by \u00a74.5, is that a field with <code>ACC_FINAL<\/code> set never has its value set <strong>after construction of the object<\/strong>:<\/p>\n<blockquote>\n<p>Declared final; never directly assigned to after object construction (JLS \u00a717.5).<\/p>\n<\/blockquote>\n<p>So, we&#8217;re in a bit of a pickle &#8211; we expect behavior of this during <em>run-time<\/em>, but not during <em>compile-time<\/em>. And why does IntelliJ raise a mild fuss when I have <code>static<\/code> in that field, but not when I don&#8217;t?<\/p>\n<p>First, back to <code>throws<\/code> &#8211; there&#8217;s only a compile-time error with that statement if one of these three pieces aren&#8217;t satisfied:<\/p>\n<ul>\n<li>The expression being thrown is unchecked or null,<\/li>\n<li>You <code>try<\/code> to <code>catch<\/code> the exception, and you&#8217;re <code>catch<\/code>ing it with the right type, or<\/li>\n<li>The expression being thrown is something that can actually thrown, per \u00a78.4.6 and \u00a78.8.5.<\/li>\n<\/ul>\n<p>So compiling a constructor with a <code>throws<\/code> is legitimate. It just so happens that, at run-time, it will always complete abruptly.<\/p>\n<blockquote>\n<p>If a throw statement is contained in a constructor declaration, but its value is not caught by some try statement that contains it, then the class instance creation expression that invoked the constructor will complete abruptly because of the throw (\u00a715.9.4).<\/p>\n<\/blockquote>\n<p>Now, onto that blank <code>final<\/code> field. There&#8217;s a curious piece to them &#8211; their assignment only matters <em>after<\/em> the end of the constructor, emphasis theirs.<\/p>\n<blockquote>\n<p><strong>A blank final instance variable must be definitely assigned (\u00a716.9) at the end of every constructor (\u00a78.8) of the class in which it is declared; otherwise a compile-time error occurs.<\/strong><\/p>\n<\/blockquote>\n<p>What if we <em>never<\/em> reach the end of the constructor?<\/p>\n<p>First program: Normal instantiation of a <code>static final<\/code> field, decompiled:<\/p>\n<pre><code>\/\/ class version 51.0 (51)\n\/\/ access flags 0x21\npublic class com\/stackoverflow\/sandbox\/DecompileThis {\n\n    \/\/ compiled from: DecompileThis.java\n\n    \/\/ access flags 0x1A\n    private final static I i = 10\n\n    \/\/ access flags 0x1\n    public ()V\n            L0\n    LINENUMBER 7 L0\n    ALOAD 0\n    INVOKESPECIAL java\/lang\/Object. ()V\n            L1\n    LINENUMBER 9 L1\n            RETURN \/\/  0) {\n        return true;\n    } else {\n        throw new IllegalStateException(\"Non-natural number!?\");\n    }\n}\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Interestingly enough, the code will compile whether or not the field is marked static &#8211; and in IntelliJ, it will complain (but compile) with the static field, and not say a word with the non-static field. You&#8217;re right in that JLS \u00a78.1.3.2 has certain rules regarding [static] final fields. However, there&#8217;s a few other rules [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,1],"tags":[],"class_list":["post-4818","post","type-post","status-publish","format-standard","hentry","category-semantic","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/4818","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/comments?post=4818"}],"version-history":[{"count":1,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/4818\/revisions"}],"predecessor-version":[{"id":8782,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/4818\/revisions\/8782"}],"wp:attachment":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/media?parent=4818"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/categories?post=4818"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/tags?post=4818"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}