{"id":4407,"date":"2014-03-30T10:39:58","date_gmt":"2014-03-30T10:39:58","guid":{"rendered":"https:\/\/unknownerror.org\/index.php\/2014\/03\/30\/is-there-any-reason-that-java-uses-late-static-binding-for-overloaded-methods-in-the-same-class-collection-of-common-programming-errors\/"},"modified":"2022-08-30T15:42:27","modified_gmt":"2022-08-30T15:42:27","slug":"is-there-any-reason-that-java-uses-late-static-binding-for-overloaded-methods-in-the-same-class-collection-of-common-programming-errors","status":"publish","type":"post","link":"https:\/\/unknownerror.org\/index.php\/2014\/03\/30\/is-there-any-reason-that-java-uses-late-static-binding-for-overloaded-methods-in-the-same-class-collection-of-common-programming-errors\/","title":{"rendered":"Is there any reason that Java uses late\/static binding for overloaded methods in the same class?-Collection of common programming errors"},"content":{"rendered":"<ul>\n<li>\n<p><strong>Efficiency.<\/strong> Single dispatch can be much more efficiently implemented by means of a virtual method table. To quote the Wikipedia article on Double dispatch:<\/p>\n<blockquote>\n<p><em>In a language supporting double dispatch, this is slightly more costly, because the compiler must generate code to calculate the method&#8217;s offset in the method table at runtime, thereby increasing the overall instruction path length.<\/em><\/p>\n<\/blockquote>\n<\/li>\n<li>\n<p><strong>Legacy.<\/strong> This is the behavior in languages that have inspired Java, such as C++, Smalltalk and Eiffel. At the very least, single dispatch follows the principle of least astonishment.<\/p>\n<\/li>\n<li>\n<p><strong>Complexity.<\/strong> The specification on how to determine which method to call is a quite interesting read. It is <em>amazingly<\/em> complex, and how to push the complexity over from the compiler to the JVM is by no means obvious. Consider for example the following snippet:<\/p>\n<pre><code>class A {                          .--------------.\n    void foo(Object o) {}          |      A       |\n}                                  '--------------'\n                                          |\nclass B extends A {                .--------------.\n    void foo(Integer i) {}         |      B       |\n}                                  '--------------'\n                                          |\nclass C extends B {                .--------------.\n    void foo(Number n) {}          |      C       |\n}                                  '--------------'\n<\/code><\/pre>\n<p>now which method should be called here:<\/p>\n<pre><code>A c = new C();\nObject i = new Integer(0);\nc.foo(i);\n<\/code><\/pre>\n<p>According to the runtime type of the callee <code>C.foo<\/code> should be called while according to the runtime type of the argument <code>B.foo<\/code> should be called.<\/p>\n<p>One option would be to resolve this the same way as a call <code>staticMethod(c, i)<\/code> would be resolved in the presence of <code>staticMethod(A, Object)<\/code>, <code>staticMethod(B, Integer)<\/code> and <code>staticMethod(C, Number)<\/code>. (Note however that in this case neighter <code>B.foo<\/code> nor <code>C.foo<\/code> would be called, as suggested above.)<\/p>\n<p>Another option would be to choose the method <em>primarily<\/em> based on the type of the callee and <em>secondarily<\/em> based on the types of the arguments, in which case <code>C.foo<\/code> would be called.<\/p>\n<p>I&#8217;m not saying that it is impossible to pin down a well defined semantics, but I it would arguably make the rules even more complex, and possibly even counter-intuitive in some aspects. In the case of early binding, at least the compiler and\/or IDE can aid the developer by giving guarantees of what will actually happen in runtime.<\/p>\n<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Efficiency. Single dispatch can be much more efficiently implemented by means of a virtual method table. To quote the Wikipedia article on Double dispatch: In a language supporting double dispatch, this is slightly more costly, because the compiler must generate code to calculate the method&#8217;s offset in the method table at runtime, thereby increasing the [&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-4407","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\/4407","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=4407"}],"version-history":[{"count":1,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/4407\/revisions"}],"predecessor-version":[{"id":8788,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/4407\/revisions\/8788"}],"wp:attachment":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/media?parent=4407"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/categories?post=4407"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/tags?post=4407"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}