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