嵌套五个条件运算符

时间:2011-04-14 10:49:11

标签: java compiler-construction

是否可以在Java中嵌套5个以上的“条件运算符”。我问,因为当我尝试编译此代码时,我似乎会导致编译器异常:

public Object getValue() {
        return
            number  != null ? number    :
            string  != null ? string    :
            bool    != null ? bool      :
            date    != null ? date      :
            list    != null ? list      :
            null;
}

我已将其缩小到此代码,因为如果我注释掉最后一行,它似乎可以正常编译。

public Object getValue() {
        return
            number  != null ? number    :
            string  != null ? string    :
            bool    != null ? bool      :
            date    != null ? date      :
//        list    != null ? list      :
            null;
}

有没有人知道这是否是java编译器的限制,或者我跳到错误的结论,如果其他人可以尝试重现这一点,那将是很好的。如果有人感兴趣,我已复制并在此处Stack Trace发布编译器中的https://gist.github.com/919284

请注意,很可能编译器中的错误不是我的代码,因为输出显示“请在Java Developer Connect站点上提交错误”(或类似内容)。我在这里问,因为我不确定那个bug报告会包含什么。


编辑: Chris L复制了这个,见他的answer

6 个答案:

答案 0 :(得分:1)

我只能在eclipse 3.5和javac 1.6.0_u24中确认这个编译没有错误:

public class Test {
    Object number=null, string=null, bool=null, date=null, list=null;

    public Object getValue() {
        return
            number  != null ? number    :
            string  != null ? string    :
            bool    != null ? bool      :
            date    != null ? date      :
            list    != null ? list      :
            null;
    }
}

答案 1 :(得分:1)

没有这么低的限制。方法必须编译为少于64KB的字节码。

我编写了你的​​例子。你有什么理由没有一个领域吗?

编辑:添加了设置器以检查有效类型。

public class Holder implements Serializable {
    Serializable value;

    public void setValue(Number value) {
        this.value = value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public void setValue(Boolean value) {
        this.value = value;
    }

    public void setValue(Date value) {
        this.value = value;
    }

    public <L extends List & Serializable> void setValue(L value) {
        this.value = value;
    }

    public Serializable getValue() {
        return value;
    }
}

答案 2 :(得分:1)

这对于ideone编译很好:

    public static void main (String[] args) throws java.lang.Exception
    {
        Object number = null;
        Object string = null;
        Object list = null;
        Object bool = null;
        Object date = null;


        Object o = 
        number  != null ? number    :
        string  != null ? string    :
        bool    != null ? bool      :
        date    != null ? date      :
        list    != null ? list      :
        null;

    }

仔细检查list是否以在方法内可访问的方式声明。


可能是您的java编译器中的错误。我建议你将你的java更新到最新的和最好的(如果有的话)并重现。您可以根据需要安装任意数量的Java版本。

答案 3 :(得分:1)

我认为语法上没有限制。我猜想java编译器会扩展其解析树,就像深度if / else if - nesting一样。

答案 4 :(得分:1)

我重现了你的错误(在Mac上使用Sun JDK 1.6.0_24)。我把你的课程简化为:

import java.util.ArrayList;
import java.util.Date;

public class Test3 {

    private Number number;
    private String string;
    private Boolean bool; // Replace Boolean with Object, and it compiles!
    private Date date;
    private ArrayList<String> list; // Replace ArrayList with List, and it
                                    // compiles!

    public Object getValue() {
        return number != null ? number :
               string != null ? string :
               bool != null ? bool :
               date != null ? date :
               list != null ? list :
               null;
    }
}

我的堆栈跟踪与您的堆栈跟踪基本相同。 (顺便说一下,它与GWT无关。)

An exception has occurred in the compiler (1.6.0_24). Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport)  after checking the Bug Parade for duplicates. Include your program and the following diagnostic in your report.  Thank you.
java.lang.AssertionError
    at com.sun.tools.javac.jvm.Code$State.forceStackTop(Code.java:1688)
    at com.sun.tools.javac.jvm.Gen.visitConditional(Gen.java:1679)
    at com.sun.tools.javac.tree.JCTree$JCConditional.accept(JCTree.java:1021)
    at com.sun.tools.javac.jvm.Gen.genExpr(Gen.java:818)
    at com.sun.tools.javac.jvm.Gen.visitConditional(Gen.java:1678)
    at com.sun.tools.javac.tree.JCTree$JCConditional.accept(JCTree.java:1021)
    at com.sun.tools.javac.jvm.Gen.genExpr(Gen.java:818)
    at com.sun.tools.javac.jvm.Gen.visitConditional(Gen.java:1678)
    at com.sun.tools.javac.tree.JCTree$JCConditional.accept(JCTree.java:1021)
    at com.sun.tools.javac.jvm.Gen.genExpr(Gen.java:818)
    at com.sun.tools.javac.jvm.Gen.visitReturn(Gen.java:1626)
    at com.sun.tools.javac.tree.JCTree$JCReturn.accept(JCTree.java:1138)
    at com.sun.tools.javac.jvm.Gen.genDef(Gen.java:665)
    at com.sun.tools.javac.jvm.Gen.genStat(Gen.java:700)
    at com.sun.tools.javac.jvm.Gen.genStat(Gen.java:686)
    at com.sun.tools.javac.jvm.Gen.genStats(Gen.java:737)
    at com.sun.tools.javac.jvm.Gen.visitBlock(Gen.java:1013)
    at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:739)
    at com.sun.tools.javac.jvm.Gen.genDef(Gen.java:665)
    at com.sun.tools.javac.jvm.Gen.genStat(Gen.java:700)
    at com.sun.tools.javac.jvm.Gen.genMethod(Gen.java:893)
    at com.sun.tools.javac.jvm.Gen.visitMethodDef(Gen.java:866)
    at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:639)
    at com.sun.tools.javac.jvm.Gen.genDef(Gen.java:665)
    at com.sun.tools.javac.jvm.Gen.genClass(Gen.java:2198)
    at com.sun.tools.javac.main.JavaCompiler.genCode(JavaCompiler.java:617)
    at com.sun.tools.javac.main.JavaCompiler.generate(JavaCompiler.java:1289)
    at com.sun.tools.javac.main.JavaCompiler.generate(JavaCompiler.java:1259)
    at com.sun.tools.javac.main.JavaCompiler.compile2(JavaCompiler.java:765)
    at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:730)
    at com.sun.tools.javac.main.Main.compile(Main.java:353)
    at com.sun.tools.javac.main.Main.compile(Main.java:279)
    at com.sun.tools.javac.main.Main.compile(Main.java:270)
    at com.sun.tools.javac.Main.compile(Main.java:69)
    at com.sun.tools.javac.Main.main(Main.java:54)

答案 5 :(得分:1)

我知道这是一篇很老的帖子,但是我最近的经历可能会让那些感兴趣的人对这个问题有所了解。这是值得注意的事情。

基本上,我通过在其他一个类中实现Comparable来“破坏”一些现有代码。这是一个精简版本,生成相同的“编译器中发生异常......”

如果嵌套条件中的表达式少于5个,或者如果USDollars类没有实现Comparable,则此代码将编译。


    public class TestHit
      {
      protected final String fSymbol;
      protected final long fTime;
      protected final USDollars fBasePrice;

      public TestHit(String aSymbol, long aTime, int aBasePrice)
        {
        fSymbol = aSymbol;
        fTime = aTime;
        fBasePrice = new USDollars(aBasePrice);
        }

      public Object field(int aIndex)
        {
        return (aIndex == 0)? fSymbol
             : (aIndex == 1)? fTime
             : (aIndex == 2)? fBasePrice
             : (aIndex == 3)? new Integer(4)   // comment out this line and it compiles
             : "?";
        }
      }

    final class USDollars
      implements Comparable<USDollars> // comment out this line and it compiles
      {
      private int cents;

      public USDollars() { this(0); }
      public USDollars(int cents) { this.cents = cents; }
      public USDollars(int dollars, int cents) { this(cents + 100*dollars); }

      public int cents() { return cents; }

    // @Override
      public int compareTo(USDollars other) { return this.cents - other.cents; }
      }

顺便说一句,快速解决方法是修改代码如下(丑陋但是有效):


      public Object field(int aIndex)
        {
        if (aIndex == 2)
           return fBasePrice;
        return (aIndex == 0)? fSymbol
             : (aIndex == 1)? fTime
             : (aIndex == 3)? new Integer(4)   // comment out this line and it compiles
             : "?";
        }