7

Netbeans is saying that my ternary operator isn't a statement. How come?

int direction;
direction = (Math.random() < 0.5) ? 0 : 1; // direction is either L or R (0 or 1)
direction == 0 ? System.out.print('L') : System.out.print('R');

I tried it's if/then/else counterpart and it works fine:

int direction;
direction = (Math.random() < 0.5) ? 0 : 1; // direction is either L or R (0 or 1)
if(direction == 0){
    System.out.print('L');
} else {
    System.out.print('R');
}
Jamie Kudla
  • 872
  • 3
  • 17
  • 37
  • 1
    In Java, a 0 has no boolean representation. Only boolean expressions can be used for that. – Kon Jul 14 '13 at 02:15
  • possible duplicate of [Why doesn't this method work? Java ternary operator](http://stackoverflow.com/questions/16876698/why-doesnt-this-method-work-java-ternary-operator) – Paul Bellora Jul 14 '13 at 02:58

3 Answers3

16

The statements in the ternary operator need to be non-void. They need to return something.

System.out.println(direction == 0 ? 'L' : 'R');
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
9

A ternary operator is intended to evaluate one of two expressions, not to execute one of two statements. (Invoking a function can be an expression if the function is declared to return a value; however, System.out is a PrintStream and PrintStream.print is a void function.) You can either stick with the if...else structure for what you're trying to do or you can do this:

System.out.print(direction == 0 ? 'L' : 'R');

NOTE: The comment by @iamcreasy points out a bit of imprecision in how I phrased things above. An expression can evaluate to nothing, so what I should have said was that a ternary operator evaluates one of two non-void expressions. According to the Java Language Specification §15.25:

It is a compile-time error for either the second or the third operand expression to be an invocation of a void method.

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
  • 1
    But according to [JLS 14.8](https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.8) MethodInvocation is an Expression Statement. So does it mean an expression can return void? (In general cases) – Quazi Irfan Apr 19 '15 at 08:43
  • @iamcreasy - An expression can indeed be void (I wouldn't use "return void" because "return" has a specific technical meaning in JLS) but not in general cases, According to [JLS §15.1](https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.1), the result of evaluating an expression can be a variable (akin to an _lvalue_ in C), a value, or nothing (a void expression). However, a void expression _"can be used only as an expression statement (§14.8), because every other context in which an expression can appear requires the expression to denote something."_ – Ted Hopp Apr 19 '15 at 14:43
5

From the JLS section 15.25. Conditional Operator ?:

It is a compile-time error for either the second or the third operand expression to be an invocation of a void method.

both the second and third operand expression here:

direction == 0 ? System.out.print('L') : System.out.print('R');

are void so this is a not a valid use of a ternary expression. You could either stick to the if else or use something similar to this alternative:

System.out.print( direction == 0 ? 'L' : 'R' );

Also the logic here is not correct:

direction = (int)(Math.random() * 1);

direction will always evaluate to 0 since Math.random() generates numbers in the range [0.0,1.0) which means it does not include 1.0 and casting a double to int will just drop the decimals. Using nextInt(2) is a good alternative.

Community
  • 1
  • 1
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
  • +1 for the catch about the use of `Math.random()`. OP should be using `Math.random()*2` or creating a `java.util.Random` object and using `nextInt(2)`. – Ted Hopp Jul 14 '13 at 02:41
  • Yes, actually I caught that as soon as I tested the program. changed it to direction = (Math.random() < 0.5) ? 0 : 1; – Jamie Kudla Jul 14 '13 at 23:31