有如下代码 package com.hzt; import java.lang.reflect.Constructor; class Person{ public Person() { } public Person(String name){ this.name=name; } public Person(int age){ this.age=age; } public Person(String name, int age) { this.age=age; this.name=name; } public String getName() { return name; } public int getAge() { return age; } @Override public String toString(){ return "["+this.name+" "+this.age+"]"; } private String name; private int age; } class hello{ public static void main(String[] args) { Class<?> demo=null; try{ demo=Class.forName("com.hzt.Person"); }catch (Exception e) { e.printStackTrace(); } Person per1=null; Person per2=null; Person per3=null; Person per4=null; //取得全部的构造函数 Constructor<?> cons[]=demo.getConstructors(); try{ per1=(Person)cons[2].newInstance(); per2=(Person)cons[3].newInstance("Rollen"); per3=(Person)cons[1].newInstance(20); per4=(Person)cons[0].newInstance("Rollen",20); }catch(Exception e){ e.printStackTrace(); } System.out.println(per1); System.out.println(per2); System.out.println(per3); System.out.println(per4); } } 反射调用其构造函数的时候,发现cons[]数组中的顺序无法确定,如果是直接run的话,顺序是 2 3 1 0,但是如果是debug的话,那么顺序就是 3 2 1 0。 使用getConstructors()函数时,返回的构造函数的顺序如何确定?为什么在debug和run的顺序还不同? 谢谢! 回复讨论(解决方案) 不要这样,用指定的构造方法: public static void main(String[] args) { Class<?> demo = null; try { demo = Class.forName("com.hzt.Person"); Constructor cons0 = demo.getConstructor(); Constructor cons1 = demo.getConstructor(String.class); Constructor cons2 = demo.getConstructor(int.class); Constructor cons3 = demo.getConstructor(String.class,int.class); Person per1 = (Person) cons0.newInstance(); Person per2 = (Person) cons1.newInstance("Rollen"); Person per3 = (Person) cons2.newInstance(20); Person per4 = (Person) cons3.newInstance("Rollen", 20); System.out.println(per1); System.out.println(per2); System.out.println(per3); System.out.println(per4); } catch (Exception e) { e.printStackTrace(); } } API并没有说要以什么顺序返回 我看了Class 的代码, 第一次取得getConstructors还是掉native函数的。 我猜测还是读.class文件来分析出来的。 所以最可能是的构造函数在.class文件里的顺序。 也许debug和run的class文件不一样? hoho。 随便猜猜。 我试下来顺序是一致的,不管是run还是debug,都是按照constructor声明的顺序排列,换了一下constructor顺序,也是按照声明顺序。 用的是jdk1.6.0_24 我试下来顺序是一致的,不管是run还是debug,都是按照constructor声明的顺序排列,换了一下constructor顺序,也是按照声明顺序。 用的是jdk1.6.0_24 我的JDK版本是 1.7.0_05-b05 构造函数顺序修改后,虽然下面调用的顺序也会改,但是也还不是按照声明顺序的 引用 4 楼 的回复: 我试下来顺序是一致的,不管是run还是debug,都是按照constructor声明的顺序排列,换了一下constructor顺序,也是按照声明顺序。 用的是jdk1.6.0_24 我的JDK版本是 1.7.0_05-b05 构造函数顺序修改后,虽然下面调用的顺序也会改,但是也还不是按照声明顺序的 你换下1.6看看,我换成1.7之后照样是声明顺序,但如果再增加一个constructor的话,顺序就乱了。如果可以看到native方法,getDeclaredConstrtuctors0 我看了Class 的代码, 第一次取得getConstructors还是掉native函数的。 我猜测还是读.class文件来分析出来的。 所以最可能是的构造函数在.class文件里的顺序。 也许debug和run的class文件不一样? hoho。 随便猜猜。 public class com.hzt.Hello extends java.lang.Object{ public com.hzt.Hello(); Code: 0: aload_0 1: invokespecial #8; //Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: aconst_null 1: astore_1 2: ldc #16; //String com.hzt.Person 4: invokestatic #18; //Method java/lang/Class.forName:(Ljava/lang/String;)Ljava/la 7: astore_1 8: goto 16 11: astore_2 12: aload_2 13: invokevirtual #24; //Method java/lang/Exception.printStackTrace:()V 16: aload_1 17: invokevirtual #29; //Method java/lang/Class.getConstructors:()[Ljava/lang/reflec 20: astore_2 21: getstatic #33; //Field java/lang/System.out:Ljava/io/PrintStream; 24: aload_2 25: iconst_0 26: aaload 27: invokevirtual #39; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V 30: getstatic #33; //Field java/lang/System.out:Ljava/io/PrintStream; 33: aload_2 34: iconst_1 35: aaload 36: invokevirtual #39; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V 39: getstatic #33; //Field java/lang/System.out:Ljava/io/PrintStream; 42: aload_2 43: iconst_2 44: aaload 45: invokevirtual #39; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V 48: getstatic #33; //Field java/lang/System.out:Ljava/io/PrintStream; 51: aload_2 52: iconst_3 53: aaload 54: invokevirtual #39; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V 57: getstatic #33; //Field java/lang/System.out:Ljava/io/PrintStream; 60: aload_2 61: iconst_4 62: aaload 63: invokevirtual #39; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V 66: return Exception table: from to target type 2 8 11 Class java/lang/Exception } 如果?assembly code角度看,貌似看不出什??果 JNIEXPORT jobjectArray JNICALL JVM_GetClassDeclaredConstructors(JNIEnv *env, jclass ofClass, jboolean publicOnly) { - NYI(); + ArrayObject* ret = 0; + JavaObject* tmp = 0; + JavaObject* Cl = 0; + llvm_gcroot(Cl, 0); + llvm_gcroot(ret, 0); + llvm_gcroot(tmp, 0); + + BEGIN_JNI_EXCEPTION + + Cl = *(JavaObject**)ofClass; + + Jnjvm* vm = JavaThread::get()->getJVM(); + UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false); + + if (cl->isArray() || cl->isInterface() || cl->isPrimitive()) { + ret = (ArrayObject*)vm->upcalls->constructorArrayClass->doNew(0, vm); + } else { + UserClass* realCl = cl->asClass();; + JnjvmClassLoader* classLoader = cl->classLoader; + uint32 size = 0; + + for (uint32 i = 0; i < realCl->nbVirtualMethods; ++i) { + JavaMethod* meth = &realCl->virtualMethods[i]; + bool pub = isPublic(meth->access); + if (meth->name->equals(classLoader->bootstrapLoader->initName) && + (!publicOnly || pub)) { + ++size; + } + } + + ret = (ArrayObject*)vm->upcalls->constructorArrayClass->doNew(size, vm); + + sint32 index = 0; + for (uint32 i = 0; i < realCl->nbVirtualMethods; ++i) { + JavaMethod* meth = &realCl->virtualMethods[i]; + bool pub = isPublic(meth->access); + if (meth->name->equals(classLoader->bootstrapLoader->initName) && + (!publicOnly || pub)) { + UserClass* Cons = vm->upcalls->newConstructor; + JavaObject * pArr = meth->getParameterTypes(classLoader); + JavaObject * eArr = meth->getExceptionTypes(classLoader); + tmp = Cons->doNew(vm); + vm->upcalls->initConstructor->invokeIntSpecial(vm, Cons, tmp, + &Cl, /* declaringClass */ + &pArr, /* parameterTypes */ + &eArr, /* checkedExceptions */ + meth->access, /* modifiers */ + i, /* slot */ + NULL, /* String signature */ + NULL, /* annotations */ + NULL /* parameterAnnotations */ + ); + ArrayObject::setElement(ret, tmp, index); + index++; + } + } + } + + RETURN_FROM_JNI((jobjectArray)th->pushJNIRef(ret)); + + END_JNI_EXCEPTION + + return 0; } https:///viewvc/llvm-project/vmkit/trunk/lib/J3/ClassLib/OpenJDK/OpenJDK.inc?r1=143672&r2=143671&pathrev=143672 既然是用反射。。。 你怎么知道人家的构造方法是怎么定义的 无需关心顺序 如果是指定了参数类型列表,那么你必然知道如何传入参数 如果是直接获取构造数组,那么你在遍历的时候,可以通过getParameterTypes来获得参数类型列表 然后就可以继续做了 送LZ一句话:不要去关心不需要你关心的东西~ public Constructor<?>[] getDeclaredConstructors() throws SecurityException Returns an array of Constructor objects reflecting all the constructors declared by the class represented by this Class object. These are public, protected, default (package) access, and private constructors. The elements in the array returned are not sorted and are not in any particular order. If the class has a default constructor, it is included in the returned array. This method returns an array of length 0 if this Class object represents an interface, a primitive type, an array class, or void. See The Java Language Specification, section 8.2. getConstructors() 和 getDeclaredConstructors 应该是彼此间重用了的。 api说明了返回无特定顺序,代码也没有直接表明是按某特定顺序。 超类-子类顺序 public Constructor<?>[] getDeclaredConstructors() throws SecurityException Returns an array of Constructor objects reflecting all the constructors declared …… 既然说明里说了没有任何顺序,看来是真没有顺序了 返回的构造器数组是不依赖于声明顺序的,这是jdk本身决定的,他就没有保证顺序 返回的构造器数组是不依赖于声明顺序的,这是jdk本身决定的,他就没有保证顺序 返回的构造器数组是不依赖于声明顺序的,这是jdk本身决定的,他就没有保证顺序 引用 11 楼 的回复: public Constructor<?>[] getDeclaredConstructors() throws SecurityException Returns an array of Constructor objects reflecting all the constructors declared …… 既然说明里说了没有任何顺序,看来是真…… 他可能认为方法声明顺序没有实际使用意义 and/or 实现排序返回也有一定代价 原来如此,学习了 |
|