简体   繁体   中英

Nesting Five Conditional Operators

Is it possible to nest more than 5 'Conditional Operators' in Java. I ask because it seems that I cause a compiler exception when I try to compile this code:

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

I have narrowed it down to this code because if I comment out the last line it seems to compile fine.

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

Does anybody else know if this is a limitation of the java compiler or am I jumping to false conclusions, it would be great if someone else could try to reproduce this. If anybody is interested I have reproduced and posted the Stack Trace from the compiler here https://gist.github.com/919284 .

Note that it is very likely a bug in the compiler not my code, as the output said "Please File a Bug at Java Developer Connect site" (or something similar). I am asking here because I am not sure what that bug report would contain.


EDIT: Chris L has reproduced this, see his answer

I know this is an old post, but my recent experiance might shed some light on the subject for those of you who are interested. It's something to be aware of.

Basically, I "broke" some existing code by implementing Comparable in one of my other classes. Here's a stripped down version that generates the same "An exception has occurred in the compiler..."

If there are fewer than 5 expressions in the nested conditional, or if the USDollars class does not implement Comparable this code compiles.


    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; }
      }

By the way, a quick fix was to modify the code as follows (ugly but it works):


      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
             : "?";
        }

I can only confirm that this compiles without error for me in both eclipse 3.5 and 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;
    }
}

There is no limit as low as this. A method must compile to less than 64KB of byte code.

I compiled your example fine. Is there any reason you don't have just one field?

EDIT: Added setters to check valid types.

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;
    }
}

This compiles fine on 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;

    }

Double check that list is declared in a way that it is accessible inside the method.


May be a bug in your java compiler. I suggest you update your java to the latest and greatest (if there is one) and reproduce. You can install as many different versions of Java as you like.

I don't think there is a limitation while it is syntactically correct. I would guess the java compiler just will expand its parse tree like for a deep if/else if - nesting.

I reproduced your error (using Sun JDK 1.6.0_24 on Mac). I simplified your class a little bit to:

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;
    }
}

My stack trace is basically the same as yours. (It has nothing to do with GWT, by the way.)

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM