可怕的Java反射错误

可怕的Java反射错误,java,excel,reflection,Java,Excel,Reflection,所以,问题出在这里。我试图使用Java中的反射来定义一种“视图”类型,以便通过有序的方法声明输出到excel工作表。(按数字顺序排列) 从理论上讲,这应该很好,而且在一定程度上是这样的 问题是,反射方法似乎随机决定有时有效,而不是其他方法。它不会抛出异常,它会毫不费力地找到方法名,但一旦它点击布尔值检查方法是否以适当的标记开始,它有时会在j=5处停止。以下是澄清方法的代码: public boolean objectWriter(List<Object> input, String

所以,问题出在这里。我试图使用Java中的反射来定义一种“视图”类型,以便通过有序的方法声明输出到excel工作表。(按数字顺序排列)

从理论上讲,这应该很好,而且在一定程度上是这样的

问题是,反射方法似乎随机决定有时有效,而不是其他方法。它不会抛出异常,它会毫不费力地找到方法名,但一旦它点击布尔值检查方法是否以适当的标记开始,它有时会在j=5处停止。以下是澄清方法的代码:

public boolean objectWriter(List<Object> input, String sheetName, int startingRow, String tag){
    ArrayList<Object> myList = new ArrayList<>();
    jxl.write.Number number;
    Label label;

    //This is just an internal counter since we're using a for-each loop. 
    int j;
    try{
        for (int i = 0; i < input.size(); i++){
            j = 0;
            //we want to iterate over all of the available methods in the given class with reflection
            for (Method m: input.get(i).getClass().getMethods()){
                //Check to see if the method name has our requested tag, plus the appropriate counter
                //tacked on, and ZERO parameters, in our case.
                myLog.debug("this is our boolean check: " + m.getName().startsWith((tag + j)));
                if (m.getName().startsWith((tag + j))){
                    myLog.debug("m.getname inside: " + m.getName());
                    //Invoke the method, give it's return value to r (return)
                    final Object r = m.invoke(input.get(i));
                    //Since we defined in the requirements of this class that it must be a string
                    //those types of methods returned, this works just fine, just case it to
                    //String (Since String extends object) and call it a day. 
                    if (isNumeric((String)r)){
                        //if it's a number, make a number object out of it. 
                        number = new jxl.write.Number(j, startingRow + i
                        , Double.parseDouble((String)r)
                        , buildNumberFormat((String)r));

                        myList.add(number);
                    }else{
                        label = new Label(j,startingRow + i,(String)r);
                        myList.add(label);
                    }
                    j++;
                }
            }
        }
    }catch(IllegalAccessException | IllegalArgumentException | InvocationTargetException ex){
        myLog.error("There was an error working through the point class with reflection.", ex);
        return false;
    }
    boolean successfulWrite = myExcelWriter.writeInformation(myList, sheetName);
    myExcelWriter.resizeColumns(18, sheetName);
    return successfulWrite;

}
等等,等等,我给了这个方法一个标签“get”,它将按照指定的顺序拉出所有三个方法。另外,它是在使用这个特殊方法的要求中定义的,返回值都是字符串,所以我很确定这不是问题所在。 奇怪的是,如果(m.getName().startsWith((tag+j))在j=5时开始失败,我不明白为什么行
上的布尔检查有时会失败

无论如何,如果有人有任何想法,我会非常感激。我被困在这里了

同样值得注意的是,对于我给出的数据集,每次j=5都将是'else'子句。对我来说,这不仅仅是巧合,但我看不出有什么不对

编辑

如果我在布尔检查之前对“m”运行一个操作,那么它完全按照预期工作(拉出所有正确枚举的方法等)的概率会显著增加(接近99%工作),这也毫无意义。比如我如何在实际语句之前打印出布尔语句?这使得它几乎每次都能工作。但这肯定不是一个解决办法

编辑#2 根据要求,我继续将println移到调试日志中,这是一个截断的版本,但它实际上在29次内重复了该模式,同样有趣的是,如果我将输出发送到日志记录器而不是控制台,那么前面提到的成功概率会回到没有它的情况下。。。奇怪

09:02:45,881 DEBUG [root] this is our boolean check: false
09:02:45,881 DEBUG [root] this is our boolean check: false
09:02:45,881 DEBUG [root] this is our boolean check: false
09:02:45,881 DEBUG [root] this is our boolean check: false
09:02:45,881 DEBUG [root] this is our boolean check: false
09:02:45,881 DEBUG [root] this is our boolean check: false
09:02:45,881 DEBUG [root] this is our boolean check: false
09:02:45,881 DEBUG [root] this is our boolean check: false
09:02:45,881 DEBUG [root] this is our boolean check: false
09:02:45,881 DEBUG [root] this is our boolean check: false
09:02:45,881 DEBUG [root] this is our boolean check: false
09:02:45,881 DEBUG [root] this is our boolean check: false
09:02:45,881 DEBUG [root] this is our boolean check: false
09:02:45,881 DEBUG [root] this is our boolean check: false
09:02:45,881 DEBUG [root] this is our boolean check: false
09:02:45,881 DEBUG [root] this is our boolean check: false
09:02:45,881 DEBUG [root] this is our boolean check: false
09:02:45,881 DEBUG [root] this is our boolean check: false
09:02:45,882 DEBUG [root] this is our boolean check: false
09:02:45,882 DEBUG [root] this is our boolean check: false
09:02:45,882 DEBUG [root] this is our boolean check: false
09:02:45,882 DEBUG [root] this is our boolean check: false
09:02:45,882 DEBUG [root] this is our boolean check: true
09:02:45,882 DEBUG [root] m.getname inside: xGet0Label
09:02:45,882 DEBUG [root] this is our boolean check: true
09:02:45,882 DEBUG [root] m.getname inside: xGet1MD
09:02:45,882 DEBUG [root] this is our boolean check: true
09:02:45,882 DEBUG [root] m.getname inside: xGet2Easting
09:02:45,882 DEBUG [root] this is our boolean check: true
09:02:45,882 DEBUG [root] m.getname inside: xGet3Northing
09:02:45,882 DEBUG [root] this is our boolean check: true
09:02:45,882 DEBUG [root] m.getname inside: xGet4TVD
09:02:45,882 DEBUG [root] this is our boolean check: true
09:02:45,882 DEBUG [root] m.getname inside: xGet5Date
09:02:45,882 DEBUG [root] this is our boolean check: false
09:02:45,882 DEBUG [root] this is our boolean check: false
09:02:45,882 DEBUG [root] this is our boolean check: false
09:02:45,882 DEBUG [root] this is our boolean check: false
09:02:45,882 DEBUG [root] this is our boolean check: false
09:02:45,883 DEBUG [root] this is our boolean check: false
09:02:45,883 DEBUG [root] this is our boolean check: false
09:02:45,883 DEBUG [root] this is our boolean check: false
09:02:45,883 DEBUG [root] this is our boolean check: false
09:02:45,883 DEBUG [root] this is our boolean check: false
09:02:45,883 DEBUG [root] this is our boolean check: false
09:02:45,883 DEBUG [root] this is our boolean check: false
09:02:45,883 DEBUG [root] this is our boolean check: false
09:02:45,883 DEBUG [root] this is our boolean check: false
09:02:45,883 DEBUG [root] this is our boolean check: false
09:02:45,883 DEBUG [root] this is our boolean check: false
09:02:45,883 DEBUG [root] this is our boolean check: false
09:02:45,883 DEBUG [root] this is our boolean check: false
09:02:45,883 DEBUG [root] this is our boolean check: false
09:02:45,883 DEBUG [root] this is our boolean check: false
09:02:45,883 DEBUG [root] this is our boolean check: false
09:02:45,883 DEBUG [root] this is our boolean check: false
09:02:45,883 DEBUG [root] this is our boolean check: false
09:02:45,883 DEBUG [root] this is our boolean check: false
09:02:45,883 DEBUG [root] this is our boolean check: false
09:02:45,883 DEBUG [root] this is our boolean check: false
09:02:45,883 DEBUG [root] this is our boolean check: false
09:02:45,883 DEBUG [root] this is our boolean check: false
09:02:45,883 DEBUG [root] this is our boolean check: false
09:02:45,884 DEBUG [root] this is our boolean check: false
09:02:45,884 DEBUG [root] this is our boolean check: false
09:02:45,884 DEBUG [root] this is our boolean check: false
09:02:45,884 DEBUG [root] this is our boolean check: false
09:02:45,884 DEBUG [root] this is our boolean check: true
09:02:45,884 DEBUG [root] m.getname inside: xGet0Label
09:02:45,884 DEBUG [root] this is our boolean check: true
09:02:45,884 DEBUG [root] m.getname inside: xGet1MD
09:02:45,884 DEBUG [root] this is our boolean check: true
09:02:45,884 DEBUG [root] m.getname inside: xGet2Easting
09:02:45,884 DEBUG [root] this is our boolean check: true
09:02:45,884 DEBUG [root] m.getname inside: xGet3Northing
09:02:45,884 DEBUG [root] this is our boolean check: true
09:02:45,884 DEBUG [root] m.getname inside: xGet4TVD
09:02:45,884 DEBUG [root] this is our boolean check: true
09:02:45,884 DEBUG [root] m.getname inside: xGet5Date

明白了!因此,在我处理被检查方法的“排序”时,存在一个固有的缺陷。虽然我预期“getMethods()”会以不特定的顺序返回类的方法,但如果其中一个方法的顺序错误,它就不会被重新检查只是由于偶然事件,有时数字顺序的第一种方法会出现在后面的方法之前,从而导致正确的行为。通常情况下,编号为0-5的方法出现在6-14之后(这是该数据集中的范围)

因此,我的解决方案是创建一个被拒绝方法名称的“池”,然后每次检查失败时,迭代拒绝池,并确保其中一个不符合要求。如果不是这些,那就不是我们关心的方法

这会减慢触摸的速度,但在毫秒范围内

解决方案代码:

public boolean objectWriter(List<Object> input, String sheetName, int startingRow, String tag){
    ArrayList<Object> myList = new ArrayList<>();
    ArrayList<Method> methodList = new ArrayList<>();
    jxl.write.Number number;
    Label label;

    //This is just an internal counter since we're using a for-each loop. 
    int j;
    try{
        for (int i = 0; i < input.size(); i++){
            j = 0;
            //we want to iterate over all of the available methods in the given class with reflection
            for (Method m: input.get(i).getClass().getDeclaredMethods()){
                //Check to see if the method name has our requested tag, plus the appropriate counter
                //tacked on, and ZERO parameters, in our case.
                if (m.getName().startsWith((tag + j))){
                    //Invoke the method, give it's return value to r (return)
                    final Object r = m.invoke(input.get(i));
                    //Since we defined in the requirements of this class that it must be a string
                    //those types of methods returned, this works just fine, just case it to
                    //String (Since String extends object) and call it a day. 
                    if (isNumeric((String)r)){
                        //if it's a number, make a number object out of it. 
                        number = new jxl.write.Number(j, startingRow + i
                        , Double.parseDouble((String)r)
                        , buildNumberFormat((String)r));

                        myList.add(number);
                    }else{
                        label = new Label(j,startingRow + i,(String)r);
                        myList.add(label);
                    }
                    j++;
                }else{
                    methodList.add(m);
                    for (int x = 0; x < methodList.size(); x++){
                        if (methodList.get(x).getName().startsWith((tag + j))){
                            //Invoke the method, give it's return value to r (return)
                            final Object r = methodList.get(x).invoke(input.get(i));
                            //Since we defined in the requirements of this class that it must be a string
                            //those types of methods returned, this works just fine, just case it to
                            //String (Since String extends object) and call it a day. 
                            if (isNumeric((String)r)){
                                //if it's a number, make a number object out of it. 
                                number = new jxl.write.Number(j, startingRow + i
                                , Double.parseDouble((String)r)
                                , buildNumberFormat((String)r));

                                myList.add(number);
                            }else{
                                label = new Label(j,startingRow + i,(String)r);
                                myList.add(label);
                            }
                            j++;
                            //methodList.remove(x);
                            break;
                        }
                    }
                }
            }
        }
    }catch(IllegalAccessException | IllegalArgumentException | InvocationTargetException ex){
        myLog.error("There was an error working through the point class with reflection.", ex);
        return false;
    }
    boolean successfulWrite = myExcelWriter.writeInformation(myList, sheetName);
    myExcelWriter.resizeColumns(18, sheetName);
    return successfulWrite;

}
public boolean objectWriter(列表输入、字符串sheetName、int startingRow、字符串标记){
ArrayList myList=新的ArrayList();
ArrayList methodList=新的ArrayList();
jxl.write.Number;
标签;
//这只是一个内部计数器,因为我们对每个循环使用一个。
int j;
试一试{
对于(int i=0;ipublic boolean objectWriter(List<Object> input, String sheetName, int startingRow, String tag){
    ArrayList<Object> myList = new ArrayList<>();
    ArrayList<Method> methodList = new ArrayList<>();
    jxl.write.Number number;
    Label label;

    //This is just an internal counter since we're using a for-each loop. 
    int j;
    try{
        for (int i = 0; i < input.size(); i++){
            j = 0;
            //we want to iterate over all of the available methods in the given class with reflection
            for (Method m: input.get(i).getClass().getDeclaredMethods()){
                //Check to see if the method name has our requested tag, plus the appropriate counter
                //tacked on, and ZERO parameters, in our case.
                if (m.getName().startsWith((tag + j))){
                    //Invoke the method, give it's return value to r (return)
                    final Object r = m.invoke(input.get(i));
                    //Since we defined in the requirements of this class that it must be a string
                    //those types of methods returned, this works just fine, just case it to
                    //String (Since String extends object) and call it a day. 
                    if (isNumeric((String)r)){
                        //if it's a number, make a number object out of it. 
                        number = new jxl.write.Number(j, startingRow + i
                        , Double.parseDouble((String)r)
                        , buildNumberFormat((String)r));

                        myList.add(number);
                    }else{
                        label = new Label(j,startingRow + i,(String)r);
                        myList.add(label);
                    }
                    j++;
                }else{
                    methodList.add(m);
                    for (int x = 0; x < methodList.size(); x++){
                        if (methodList.get(x).getName().startsWith((tag + j))){
                            //Invoke the method, give it's return value to r (return)
                            final Object r = methodList.get(x).invoke(input.get(i));
                            //Since we defined in the requirements of this class that it must be a string
                            //those types of methods returned, this works just fine, just case it to
                            //String (Since String extends object) and call it a day. 
                            if (isNumeric((String)r)){
                                //if it's a number, make a number object out of it. 
                                number = new jxl.write.Number(j, startingRow + i
                                , Double.parseDouble((String)r)
                                , buildNumberFormat((String)r));

                                myList.add(number);
                            }else{
                                label = new Label(j,startingRow + i,(String)r);
                                myList.add(label);
                            }
                            j++;
                            //methodList.remove(x);
                            break;
                        }
                    }
                }
            }
        }
    }catch(IllegalAccessException | IllegalArgumentException | InvocationTargetException ex){
        myLog.error("There was an error working through the point class with reflection.", ex);
        return false;
    }
    boolean successfulWrite = myExcelWriter.writeInformation(myList, sheetName);
    myExcelWriter.resizeColumns(18, sheetName);
    return successfulWrite;

}