i know when java compiler compiles generic type, performs type erasure , removed references generic code , arraylist<cheesecake> becomes arraylist.
the question haven't need clear answer is, whether lack of type (and therefore mandatory type-casting) causes slow down. in order words, if using standard java compiler , standard jvm 1.7 oracle:
- does bytecode include type cast?
- if yes, include run-time check check if correct type?
- does conversion take non-trivial amount of time?
- would making own
cheesecakelistclass looks identicalarraylist, ofobjects turnedcheesecakes gain (again hypothetical , not interested in side effects of having larger binary because of more classes nor duplication in code).
i not interested in other problems type erasure causes, simple answer understand jvm better do.
i interested in cost in example:
list<cheesecake> list = new arraylist<cheesecake>(); (int = 0; < list.size(); i++) { // know gets converted ((cheesecake)list.get(i)).at(me) list.get(i).eat(me); } is cast inside loop expensive and/or significant compared to:
cheesecakelist list = new cheesecakelist(); (int = 0; < list.size(); i++) { //where return of list.get() cheesecake, therefore there no casting. list.get(i).eat(me); } disclaimer: question of academic curiosity. doubt there significant performance issues type cast , removing need them wouldn't 1 of top 5 things if found performance bug in code. if reading because have performance issue favor , start profiler , find out bottle neck is. if believe in type-casting, should try , optimize somehow.
the short story: yes, there type check. here's proof -
given following classes:
// let's define generic class. public class cell<t> { public void set(t t) { this.t = t; } public t get() { return t; } private t t; } public class { static cell<string> cell = new cell<string>(); // instantiate it. public static void main(string[] args) { // now, let's use it. cell.set("a"); string s = cell.get(); system.out.println(s); } } the bytecode a.main() compiled (decompiled via javap -c a.class) follows:
public static void main(java.lang.string[]); code: 0: getstatic #20 // field cell:lp2/cell; 3: ldc #22 // string 5: invokevirtual #24 // method p2/cell.set:(ljava/lang/object;)v 8: getstatic #20 // field cell:lp2/cell; 11: invokevirtual #30 // method p2/cell.get:()ljava/lang/object; 14: checkcast #34 // class java/lang/string 17: astore_1 18: getstatic #36 // field java/lang/system.out:ljava/io/printstream; 21: aload_1 22: invokevirtual #42 // method java/io/printstream.println:(ljava/lang/string;)v 25: return } as can in offset 14, result of cell.get() type checked verify indeed string:
14: checkcast #34 // class java/lang/string this incur runtime penalty. however, jvm pretty optimized, effect of minimal.
the longer story:
how go implementing such cheesecakelist class? wouldn't class define array hold elements? advised every assignment array incurs hidden typecheck. won't gain as think (although program perform more read operations write operations cheesecak[] array give something).
bottom line: don't optimize prematurely.
a final comment. people think type erasure means cell<string> compiled cell<object>. that's not true. erasure applied definition of generic class/method. not applied usage sites of these classes/methods.
in other words, class cell<t> compiled if written cell<object>. if t has uppper bound (say number) compiled cell<number>. in other places in code, typically variables/parameters type instantiation of cell class (such cell<string> mycell), erasure not applied. fact mycell of type cell<string> kept in classfile. allows compiler typecheck program correctly.
Comments
Post a Comment