{"id":269,"date":"2011-06-02T07:30:51","date_gmt":"2011-06-02T07:30:51","guid":{"rendered":"https:\/\/kari.world.ikari.fi\/2011\/06\/02\/analyzing-byte-cote\/"},"modified":"2011-06-02T07:30:51","modified_gmt":"2011-06-02T07:30:51","slug":"analyzing-byte-cote","status":"publish","type":"post","link":"https:\/\/kari.world.ikari.fi\/?p=269","title":{"rendered":"Analyzing Byte Cote"},"content":{"rendered":"<p>So lets see how we can test for &#8221;param is valid type&#8221;.<\/p>\n<p><b>Bar<\/b><br \/>\n[code lang=&#8221;java&#8221;]<br \/>\npublic class Bar {<br \/>\n}<br \/>\n[\/code]<\/p>\n<p><b>Test<\/b><br \/>\n[code lang=&#8221;java&#8221;]<br \/>\npublic class Test {<br \/>\n  private static final Class<Bar> CLS = Bar.class;<\/p>\n<p>  public static void test1(Object a) {<br \/>\n    if (a instanceof Bar) {<br \/>\n       int x = 0;<br \/>\n    }<br \/>\n  }<br \/>\n  public static void test2(Object a) {<br \/>\n    if (a.getClass() == Bar.class) {<br \/>\n       int x = 0;<br \/>\n    }<br \/>\n  }<br \/>\n  public static void test3(Object a) {<br \/>\n    if (a.getClass() == CLS) {<br \/>\n       int x = 0;<br \/>\n    }<br \/>\n  }<br \/>\n}<br \/>\n[\/code]<\/p>\n<p>These translate into this<\/p>\n<p><b>Bar Disassembled: javap -c Bar<\/b><br \/>\n[code lang=&#8221;java&#8221;]<br \/>\npublic class Bar extends java.lang.Object{<br \/>\npublic Bar();<br \/>\n  Code:<br \/>\n   0:   aload_0<br \/>\n   1:   invokespecial   #1; \/\/Method java\/lang\/Object.&#8221;<init>&#8221;:()V<br \/>\n   4:   return<\/p>\n<p>}<br \/>\n[\/code]<\/p>\n<p><b>Test Disassembled: javap -c Test<\/b><br \/>\n[code lang=&#8221;java&#8221;]<br \/>\npublic class Test extends java.lang.Object{<br \/>\npublic Test();<br \/>\n  Code:<br \/>\n   0:   aload_0<br \/>\n   1:   invokespecial   #1; \/\/Method java\/lang\/Object.&#8221;<init>&#8221;:()V<br \/>\n   4:   return<\/p>\n<p>public static void test1(java.lang.Object);<br \/>\n  Code:<br \/>\n   0:   aload_0<br \/>\n   1:   instanceof      #2; \/\/class Bar<br \/>\n   4:   ifeq    9<br \/>\n   7:   iconst_0<br \/>\n   8:   istore_1<br \/>\n   9:   return<\/p>\n<p>public static void test2(java.lang.Object);<br \/>\n  Code:<br \/>\n   0:   aload_0<br \/>\n   1:   invokevirtual   #3; \/\/Method java\/lang\/Object.getClass:()Ljava\/lang\/Class;<br \/>\n   4:   ldc_w   #2; \/\/class Bar<br \/>\n   7:   if_acmpne       12<br \/>\n   10:  iconst_0<br \/>\n   11:  istore_1<br \/>\n   12:  return<\/p>\n<p>public static void test3(java.lang.Object);<br \/>\n  Code:<br \/>\n   0:   aload_0<br \/>\n   1:   invokevirtual   #3; \/\/Method java\/lang\/Object.getClass:()Ljava\/lang\/Class;<br \/>\n   4:   getstatic       #4; \/\/Field CLS:Ljava\/lang\/Class;<br \/>\n   7:   if_acmpne       12<br \/>\n   10:  iconst_0<br \/>\n   11:  istore_1<br \/>\n   12:  return<\/p>\n<p>static {};<br \/>\n  Code:<br \/>\n   0:   ldc_w   #2; \/\/class Bar<br \/>\n   3:   putstatic       #4; \/\/Field CLS:Ljava\/lang\/Class;<br \/>\n   6:   return<\/p>\n<p>}<br \/>\n[\/code]<\/p>\n<p>So what we learn from this, hopefully something. At least it seems that it&#8217;s not good idea trying to outsmart compiler, and secondly it doesn&#8217;t matter. I.e. I believe that in this case there isn&#8217;t any differerence in performance, however, it seems that instanceof version creates slightly shorter bytecode. However, <b>must<\/b> be noted that there is various very valid reasons for exact class equality instead of <code>instanceof<\/code>.<\/p>\n<p>For example,<\/p>\n<p>Ensuring that <code>equals()<\/code> produces correct results<\/p>\n<p>[code lang=&#8221;java&#8221;]<br \/>\npublic class Foo {<br \/>\n    public boolean equals(Object o) {<br \/>\n        if (o == this) {<br \/>\n            return true;<br \/>\n        } else if (o == null) {<br \/>\n            return false;<br \/>\n        }<br \/>\n        if (o.getClass() == getClass() {<br \/>\n           \/\/ &#8230;<br \/>\n        }<br \/>\n        return false;<br \/>\n    }<br \/>\n}<br \/>\n[\/code]<\/p>\n<p>[code lang=&#8221;java&#8221;]<br \/>\npublic class Bar extends Foo {<br \/>\n    \/\/ &#8230;<br \/>\n}<br \/>\n[\/code]<\/p>\n<p>Strict class equality ensures here that equals() contract is implemented properly, with <code>instanceof<\/code>, Foo could equal to Bar, but Bar would not equal to Foo.<\/p>\n<p>If you&#8217;ve developed with java long enough, you surely have had enough of horror stories of equals() -methods, which implement interesting hacks to provide equality between Apples and Oranges (naturally without any documentation, and at some point of time those hacks start to haunt you when some refactoring is done, and fixing hacks is difficult, since there ain&#8217;t any clear traces why such strange things exists at all).<\/p>\n<p><b>PS.<\/b> Please notice that &#8221;a != null&#8221; checks are irrelevant in the Test class, since it conforms into standard safe API spec convention. This convention states that all values (param or return) are <b>NON-NULL<\/b> unless otherwise stated. I.e. makes programming much easier, since that is the best default value. Thus when you conform to this convention, safe API spec is specified with minimal effort, and it also promotes using safe methods (i.e. no horror stories of methods, without any kind of specifications, returning randomly null values, which can cumulate incredible amount of highly unclear and unmaintainable code in the full call chain for such methods).<\/p>\n<p><b>References:<\/b><br \/>\n<a href=\"http:\/\/wikis.sun.com\/display\/HotSpotInternals\/PerformanceTechniques\">JavaWiki: PerformanceTechniques<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>So lets see how we can test for &#8221;param is valid type&#8221;. Bar [code lang=&#8221;java&#8221;] public class Bar { } [\/code] Test [code lang=&#8221;java&#8221;] public class Test { private static final Class CLS = Bar.class; public static void test1(Object a) { if (a instanceof Bar) { int x = 0; } } public static void&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[],"class_list":["post-269","post","type-post","status-publish","format-standard","hentry","category-java"],"_links":{"self":[{"href":"https:\/\/kari.world.ikari.fi\/index.php?rest_route=\/wp\/v2\/posts\/269","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kari.world.ikari.fi\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kari.world.ikari.fi\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kari.world.ikari.fi\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kari.world.ikari.fi\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=269"}],"version-history":[{"count":0,"href":"https:\/\/kari.world.ikari.fi\/index.php?rest_route=\/wp\/v2\/posts\/269\/revisions"}],"wp:attachment":[{"href":"https:\/\/kari.world.ikari.fi\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=269"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kari.world.ikari.fi\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=269"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kari.world.ikari.fi\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=269"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}