Java reflection - enum generate -
i make program can generate source code of class,enum , interfaces using reflection have problem enum generating.
my eumtest class
public enum enumtest{ a,b; private string r; private enumtest(){ } private void some(){ } public int[] some2(int[] b){ return b; } }
method generate enum file
private void generateenum(class<?> cls,printwriter writer) { this.writepackage(cls, writer); this.writeannotations(writer, cls.getdeclaredannotations()); writer.write(modifier.tostring(cls.getmodifiers())+ " enum " + cls.getsimplename()); this.writeimplementation(cls, writer); writer.write("{"); this.writenewline(writer); object[] cons = cls.getenumconstants(); (int = 0; < cons.length; i++) { writer.write(cons[i].tostring()); if(i != cons.length - 1) writer.write(","); } writer.write(";"); this.writenewline(writer); this.writefields(cls, writer); this.writeconstructors(cls, writer); this.writemethods(cls,writer); writer.write("}"); }
result new enum
package metaprogramovanie.test; public final enum enumtest{ a,b; private java.lang.string r; private static final metaprogramovanie.test.enumtest[] $values; private enumtest(java.lang.string arg0,int arg1){ } public static metaprogramovanie.test.enumtest[] values(){ return null; } public static metaprogramovanie.test.enumtest valueof(java.lang.string arg0){ return null; } private void some(){ } public int daco(int arg0){ return 0; } }
as can see there som errors. example modifier generate final , enum cant final, next there more methods , fields, constructor has paramaters ...
constructor generate
private void writeconstructors(class<?> cls, printwriter writer){ constructor[] cons = cls.getdeclaredconstructors(); (constructor constructor : cons) { this.writeannotations(writer, constructor.getdeclaredannotations()); writer.write(modifier.tostring(constructor.getmodifiers()) + " " + cls.getsimplename()); this.writeparameters(writer,constructor.getparameters()); writer.write("{"); this.writenewline(writer); writer.write("}"); this.writenewline(writer); } }
field generate
private void writefields(class<?> cls, printwriter writer){ field[] atr = cls.getdeclaredfields(); (field field : atr) { if(field.isenumconstant()){ system.out.println("je"); } else{ this.writeannotations(writer, field.getdeclaredannotations()); writer.write(modifier.tostring(field.getmodifiers())+" " + field.gettype().gettypename()+ " " + field.getname()); if(modifier.isstatic(field.getmodifiers())){ try{ object value = field.get(null); writer.write(" = " + this.getfieldvalue(field)); }catch(illegalaccessexception ex){ } } writer.write(";"); this.writenewline(writer); } } this.writenewline(writer); }
methods generate
private void writemethods(class<?> cls, printwriter writer){ method[] methods = cls.getdeclaredmethods(); (method met : methods) { this.writeannotations(writer, met.getdeclaredannotations()); writer.write(modifier.tostring(met.getmodifiers())+" "+met.getreturntype().gettypename() +" "+ met.getname()); this.writeparameters(writer, met.getparameters()); writer.write("{"); this.writenewline(writer); if(!met.getreturntype().equals(void.type)){ this.writemethodbody(writer,met); } this.writenewline(writer); writer.write("}"); this.writenewline(writer); } this.writenewline(writer); }
if have ideas how enum can compiled.
here explanation of why stuff.
enums implemented using lot of code synthesized compiler, "behind scenes" behave java language spec specifies, without requiring jvm drastically changed.
the java language specification says, example, that:
- an
enum
implicitlyfinal
unless there's constant body. - any
enum
implicitly declares methodsvalues()
,valueof(string)
.
for reason, got final
modifier enumtest
, , got 2 methods.
in addition, compiler synthesizes code implement of required stuff efficiently. example, source of array copied , returned method values()
placed in synthetic field named, in case, $values
. filled @ initialization of enum, , can copied whenever values()
called.
also, initialize constants, compiler adds 2 hidden parameters each of constructors. if have empty constructor, behind scenes has 2 parameters - constant's name , ordinal number. if have constructor 1 parameter, behind scenes have 3 parameters.
there additional synthetic code created when have constants own bodies.
all of these latter implementations done compiler not documented in jls , left compiler decide how implement. long enum behaves correctly result of whatever code compiler generates, free generate in way chooses.
tips overcoming of problems have encountered:
instead of using
modifier.tostring(cls.getmodifiers())
printenum
modifiers, usemodifier.tostring(cls.getmodifiers() & ~ modifier.final & ~ modifier.abstract)
this excludes
final
modifier outputabstract
modifier show if add abstract methodsenum
(and process constant bodies, haven't done far).- use
field.issynthetic()
method check whether field synthesized compiler, , not output fields method returnstrue
. rid of$values
field. - the 2 methods
values()
,valueof(string)
not considered synthetic , if usemethod.issynthetic()
on them, return false. you'll have check each method find in enum. if 1 of these 2 methods, signature , return type specified in jls, skip them , not output them.
the tricky part getting rid of 2 additional parameters of each of constructors. basically, when iterate through constructor parameters, can skip first 2 parameters. however, remember work code generated oracle compiler , not guaranteed in future versions or other compiler!
Comments
Post a Comment