所以,这就是问题所在。我试图在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;
}
因此,正如您在上面所看到的,它反过来在方法名称中查找调用者定义的“标记”以及数字。所以,如果我有一个类似的方法:
public String get0(){}
public String get1(){}
public String get2(){}
等。我给了这个方法标签'get'它会以指定的顺序拉出所有这三个方法。此外,它在使用这个特定方法的要求中定义了所有字符串的返回值,所以这不是我非常肯定的问题。
奇怪的是我无法理解为什么线if (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
答案 0 :(得分:1)
想出来!因此,我正在接近正在检查的方法的“排序”方式存在固有的错误。虽然我预计'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;
}
这是一个很好的教训,当你试图在一个固有的无序列表上强加一个订单时,请确保你很小心,因为如果你搞砸了(像我一样!)它会感觉非常不明确的行为。