方法应返回布尔值,却返回整型。

4

我需要创建一个类似于JAR包中的方法。由于没有源代码,所以我使用JD-GUI进行反编译学习。

private static boolean checkMe(Date paramDate, String paramString)
        throws REUException {
    int i = 1;
    int j, k;

    // unrelated stuff

    if (j > k)
        i = 0;
    return i;
}

您可以在方法签名中看到应该返回一个布尔值(boolean),但实际上它返回了一个整数(int),这在Java中是不被允许的。
所以,我认为JD-GUI可能有问题。

我尝试使用javap进行反汇编,但我仍然没有头绪:

输入:javap -c -s -verbose -private Class

我得到:

private static boolean checkMe(java.util.Date, java.lang.String)   throws reu.exceptions.REUException;
  Signature: (Ljava/util/Date;Ljava/lang/String;)Z
  Code:
   Stack=4, Locals=7, Args_size=2
   0:   iconst_1
   1:   istore_2
   2:   getstatic   #34; //Field iniciado:Z
   5:   ifne    44
   8:   ldc_w   #35; //class reu/modulos/STDWDATES
   11:  dup
   12:  astore_3
   13:  monitorenter
   14:  getstatic   #34; //Field iniciado:Z
   17:  ifne    32
   20:  new #35; //class reu/modulos/STDWDATES
   23:  dup
   24:  invokespecial   #36; //Method "<init>":()V
   27:  pop
   28:  iconst_1
   29:  putstatic   #34; //Field iniciado:Z
   32:  aload_3
   33:  monitorexit
   34:  goto    44
   37:  astore  4
   39:  aload_3
   40:  monitorexit
   41:  aload   4
   43:  athrow
   44:  aconst_null
   45:  getstatic   #37; //Field AlmacenFechaCal:Ljava/util/HashMap;
   48:  aload_1
   49:  invokevirtual   #38; //Method java/util/HashMap.get:(Ljava/lang/Object;)Ljava/lang/Object;
   52:  if_acmpne   67
   55:  new #39; //class reu/exceptions/REUException
   58:  dup
   59:  bipush  58
   61:  bipush  17
   63:  invokespecial   #40; //Method reu/exceptions/REUException."<init>":(II)V
   66:  athrow
   67:  getstatic   #37; //Field AlmacenFechaCal:Ljava/util/HashMap;
   70:  aload_1
   71:  invokevirtual   #38; //Method java/util/HashMap.get:(Ljava/lang/Object;)Ljava/lang/Object;
   74:  checkcast   #41; //class reu/modulos/AlmancenFechas
   77:  astore_3
   78:  aload_3
   79:  invokevirtual   #42; //Method reu/modulos/AlmancenFechas.getFechaIni:()I
   82:  istore  4
   84:  invokestatic    #43; //Method java/util/Calendar.getInstance:()Ljava/util/Calendar;
   87:  astore  5
   89:  aload   5
   91:  aload_0
   92:  invokevirtual   #44; //Method java/util/Calendar.setTime:(Ljava/util/Date;)V
   95:  aload   5
   97:  iconst_1
   98:  invokevirtual   #45; //Method java/util/Calendar.get:(I)I
   101: istore  6
   103: iload   4
   105: iload   6
   107: if_icmple   112
   110: iconst_0
   111: istore_2
   112: iload_2
   113: ireturn
  Exception table:
   from   to  target type
    14    34    37   any
    37    41    37   any
  Exceptions: 
   throws reu.exceptions.REUException

我猜线索在第113行的ireturn表达式中。根据Oracle关于ireturn的文档,它返回一个int。
在这个原始类型强制转换中,看起来像是从int到boolean的转换,与C/C++不同,是不允许的。
那怎么可能呢?有隐式转换吗?
谢谢。

1
对我来说编译不通过。应该是你的编译器出了问题。 - user3079266
它不应该编译.. 在Java中,大多数缩小转换将在编译时产生错误。 - TheLostMind
请参考这个答案,其中包含解释和示例:http://stackoverflow.com/a/8249193/2595658 - Paco Abato
@TheLostMind 我知道这段代码不能编译。这就是我提问的原因。我正在展示从 JAR 文件中反编译出来的类中的代码。 - Albert
@Antimony 从未听说过。我会去看看。谢谢 - Albert
显示剩余2条评论
2个回答

4
JVM将布尔值表示为整数:true1表示,false0表示。这就是为什么编译后的代码使用整数的原因。
换句话说,如果您编写以下方法并使用布尔值(这可能是原始源代码):
private static boolean checkMe(Date paramDate, String paramString)
       throws REUException {
   boolean i = true;
   int j, k;

    // unrelated stuff

    if (j > k)
        i = false;
    return i;
}

那么生成的字节码最后会包含ireturn


谢谢。不幸的是,我没有访问源代码的权限。我已经尝试了你所说的:编译你提供的代码,然后反编译,它显示iboolean,而不是int。这就是我不理解的地方,也是我提出问题的原因。 - Albert
那可能是JD-GUI反编译器本身的一个错误。 - M A
是的。我想没有其他选择了。我会尝试向他们报告。谢谢。 - Albert

4
JVM使用整数来表示布尔值。引自JVM规范 §2.3.4

2.3.4. 布尔类型

虽然Java虚拟机定义了布尔类型,但它对其的支持非常有限。没有Java虚拟机指令专门用于处理布尔值。相反,在Java编程语言中操作布尔值的表达式被编译为使用Java虚拟机int数据类型的值

您可以自行检查此内容:
$ cat Test.java
class Test {
    boolean m() {
        return true;    <------------
    }
}
$ javac Test.java 
$ javap -c Test
Compiled from "Test.java"
class Test {
  [...]     

  boolean m();
    Code:
       0: iconst_1      
       1: ireturn        <------------
}

@aioobe。我明白了,这意味着JD-GUI存在某种bug。尽管如此,很奇怪的是,我使用变量用JD-GUI反编译了你的示例,并显示:boolean m() {boolean bool = false; return bool; },这是正确的。 - Albert
是的,现在只是出于好奇心。如果我能找到它们,我会尝试通知项目关于这个可能的“漏洞”,或者使用另一个反编译器。谢谢。 - Albert
很可能反编译器从方法的开头开始,遇到了变量#2,它看起来像一个“int”变量,与“ireturn”的关系还没有被揭示。当遇到“ireturn”时,它没有修正变量的类型。 - Holger
好的,它在一个更简单的示例中修改了类型(请参见上面的Alberts评论),所以我仍然认为这是一个错误。 - aioobe
@aioobe:好的,但是关于在return指令之前引入变量和在引入变量与return指令之间有大量代码之间的区别的说法仍然成立。毕竟,即使错误也遵循逻辑模式,我认为这个错误是显而易见的。 - Holger
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接