有如下代码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 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的顺序还不同?
谢谢!
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();
}
}
我猜测还是读.class文件来分析出来的。
所以最可能是的构造函数在.class文件里的顺序。 也许debug和run的class文件不一样? hoho。 随便猜猜。
用的是jdk1.6.0_24
构造函数顺序修改后,虽然下面调用的顺序也会改,但是也还不是按照声明顺序的
public com.hzt.Hello();
Code:
0: aload_0
1: invokespecial #8; //Method java/lang/Object."<init>":()V
4: returnpublic 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://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/J3/ClassLib/OpenJDK/OpenJDK.inc?r1=143672&r2=143671&pathrev=143672
如果是指定了参数类型列表,那么你必然知道如何传入参数
如果是直接获取构造数组,那么你在遍历的时候,可以通过getParameterTypes来获得参数类型列表
然后就可以继续做了送LZ一句话:不要去关心不需要你关心的东西~
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说明了返回无特定顺序,代码也没有直接表明是按某特定顺序。