I'm getting an compilation error "Not a statement" for this line of code:
parallel? stats[3]++ : stats[4]++;
can't understand why?!
Quoting from this:
The following types of expressions can be made into a statement
by terminating the expression with a semicolon (;).
Assignment expressions
Any use of ++ or --
Method invocations
Object creation expressions
...
In addition to expression statements, there are two other kinds of
statements: declaration statements and control flow statements.
Obviously, your line of code above doesn't fall into any category mentioned above. Hence, the compiler throw an error. Look at the outermost, not the innermost.
The :? operator is used to return a value is not a complete replacement for the if/else and you aren't returning a value. But explain better what is the complete error, and give a better look of the code not only the line that you post.
Related
I am trying to do a simple if Statement using the ? pattern. Resulting in an "Not a statement"- Error. Can someone please explain to me why this is not happening using a normal if statement?
Error:
cursor.isNull(0) ? insert_SQL_RSServer.bindNull(0) : insert_SQL_RSServer.bindLong(0, cursor.getLong(0)); // id
No Error:
if(cursor.isNull(0))
insert_SQL_RSServer.bindNull(0);
else
insert_SQL_RSServer.bindLong(0, cursor.getLong(0));
This is completely the same behavior ....
The ternary conditional operator is an expression, and it must have a return type, which is determined by the types of the 2nd and 3rd operands.
Therefore, if your bindNull() and bindLong() methods have void return type, they can't be used in this operator.
In Java, an expression is not a statement except in the case of the following:
StatementExpression:
Assignment
PreIncrementExpression
PreDecrementExpression
PostIncrementExpression
PostDecrementExpression
MethodInvocation
ClassInstanceCreationExpression
Reference: JLS 14.8.
A ternary expression is not one of the above.
Thanks! But this is still bullshit... However..
It is the way that it is. This is how Java is specified.
This could simply be a design choice that reflected the language designers' personal taste / views on simplicity. Alternatively, there could be a deeper reason or reasons for the choice; e.g. it might have solved some issue with ambiguous parses.
Some days ago I was talking with my colleagues about this code in Java:
for( ; ; ) { }
Nothing special here, just an infinite loop.
But we wonder why this is syntactically correct. If you take a look to JLS §14.14.1 you'll see this:
for ( [ForInit] ; [Expression] ; [ForUpdate] ) Statement
I understand that ForInit and ForUpdate can be omitted. But at least I would expect that Expression is mandatory, like in while-loop:
while() {} // compile error, Expression is missed
So why can Expression be omitted on a for-loop? And even one think more - why is missed Expression resolved to true? My expectation would be that empty Expression is resolved to false.
The same think is valid for other languages (I've try it with C and JavaScript, but I believe every language with for-loops behaves in that way).
Why is an Expression clause not mandatory in for-loop (but in while-loop)? Why does empty Expression resolve to true and not to false?
The rationale starts in JLS 14.14.1.1 and continues into 14.14.1.2, emphasis mine.
If the ForInit part is not present, no action is taken.
If the Expression is not present, or it is present and the value resulting from its evaluation (including any possible unboxing) is true, then the contained Statement is executed...
The JLS permits the blank ForInit, Expression and ForUpdate statements and has conditions to deal with their absence, so omitting them is acceptable.
It is not permissible to do so with while loops, per JLS 14.12.
The Expression must have type boolean or Boolean, or a compile-time error occurs.
From this, the specification is not permitting a blank expression to be passed through, since that would result in a compile-time error per above.
If you're looking for a slightly more historical reason, the C specification mandates this as well.
Since Java took heavy inspiration from C (and is mostly implemented in it), it makes perfect sense for Java's loops to behave similarly to C's loops, and this is how they behave: expressions are optional in C's for statement, and mandatory in its while statement.
I've read Oracle's expressions tutorial and couldn't understand this.
It is well known that the following line of code is valid Java syntax:
new Object();
However, when I try this with a primitive expression:
(3 + 2);
Eclipse is showing a compile error of "The left-hand side of an assignment must be a variable".
This is true not only for primitives, but also for String literals:
"arbitraryString";
So what is the rule for an unassigned expression to be valid as a Java line of code?
The rule is in the Java Language Specification:
Certain kinds of expressions may be used as statements by following them with semicolons.
ExpressionStatement:
StatementExpression ;
StatementExpression:
Assignment
PreIncrementExpression
PreDecrementExpression
PostIncrementExpression
PostDecrementExpression
MethodInvocation
ClassInstanceCreationExpression
You see that a constructor invocation is a statement. But a String literal or mathematical expression is not.
Creating an object or calling or method can have side effects, I think this is the main reason for this, whereas nothing will ever happen with an arithmetic expression.
Line containing only
new Object();
or to be more precise
new SomeClass();
is acceptable, because code of SomeClass() constructor may be all we want.
But in case of lines containing only
"foo";
or
2;//or (2+3);
compiler knows that beside creating/reusing String literal or integer literal this code doesn't do anything else, which means it is probably some kind of programmer mistake so compiler can't accept it.
You're looking for the difference between expressions and expression-statements. Statements like myVoid(); can be written as a statement: these are void methods, etc. (that's the part you know). Expressions, like (3 + 2); and "arbitraryString", have no side-effects. They can only be treated as a value, as no code is executed. Expression-statements, like new Object(); can have side-effects and execute code, and you sometimes just want this code to be executed and ignore the returned value. The compiler therefore allows this.
if(true)
String str;
Hi, the code above gives an error like that:
Multiple markers at this line
- str cannot be resolved to a variable
- Syntax error on token "String", AssignmentOperator expected after this token
Why there is an error like this? Of course I know str will be unreachable after defined. But java doesn't gives an explanation like that. Just seemed odd to me.
This is because you put a declaration in a protected block of the conditional. However, Java declarations are not considered statements according to Java syntax.
Declarations are allowed to be mixed with statements as part of blocks enclosed in curly braces, but a single declaration is not considered a statement. This makes perfect sense, because the variable that you declare is not usable: if you wanted a declaration-initialization for its side effect, such as
if (true)
String str = someFunction();
you could use an expression statement without declaring a variable that you wouldn't be able to use anyway:
if (true)
someFunction();
Therefore, if you put a declaration by itself in a conditional or a loop, the compiler is certain that you made a mistake, and produces an error message to alert you to the problem.
Just for fun, I was trying to replace:
if (set1.add(x) == false)
{
set2.add(x);
}
with:
set1.add(x) || set2.add(x);
However, Eclipse complains:
Syntax error on token "||", invalid AssignmentOperator
The left-hand side of an assignment must be a variable
Could anybody shine some light onto these error messages? They don't make much sense to me.
As #qqilihq said in the comments try to do
boolean temp = set1.add(x) || set2.add(x);
or more awkward:
if(set1.add(x) || set2.add(x));
According to documentation java statements which can end with a semicolon are:
Assignment expressions
Any use of ++ or --
Method invocations
Object creation expressions
What you've written is not a statement it's an expression. Here you can find more about statements and expressions. So simple but worth to look.
There are a number of answers far, but I agree with Bohemian's answer that the most straightforward simplification (although it doesn't use ||) is this:
if ( !set1.add(x) ) set2.add(x);
That doesn't explain the error message though. Mustafa Genç comes closer on this, but I think it's worthwhile to look at the language specification here. exp1 || exp2 is an expression, and the problem here is that you're trying to use it in a context where a statement is expected. According to 14.8. Expression Statements, some kinds of expressions can be used where statements are expected by attaching a semicolon:
14.8. Expression Statements
Certain kinds of expressions may be used as statements by following
them with semicolons.
ExpressionStatement:
StatementExpression ;
StatementExpression:
Assignment
PreIncrementExpression
PreDecrementExpression
PostIncrementExpression
PostDecrementExpression
MethodInvocation
ClassInstanceCreationExpression
An expression statement is executed by evaluating the expression; if
the expression has a value, the value is discarded.
The reason that you can't do what you're trying to do, though, is that not every expression can be used as a statement. However, it does discuss some ways to work around this. From the same section of the specification (emphasis added):
Unlike C and C++, the Java programming language allows only certain
forms of expressions to be used as expression statements. Note that
the Java programming language does not allow a "cast to void" - void
is not a type - so the traditional C trick of writing an expression
statement such as:
(void)... ; // incorrect!
does not work. On the other hand, the Java
programming language allows all the most useful kinds of expressions
in expressions statements, and it does not require a method invocation
used as an expression statement to invoke a void method, so such a
trick is almost never needed. If a trick is needed, either an
assignment statement (§15.26) or a local variable declaration
statement (§14.4) can be used instead.
This approach is what the first snipped in Reik Val's answer is using:
boolean temp = set1.add(x) || set2.add(x);
I would just:
if (!set1.add(x))
set2.add(x);
The statement
boolean temp = set1.add(x) || set2.add(x);
and any variation thereof is dangerous. You'll hardly ever know what happens there. Note that the right expression is NOT evaludated iff the first expression is true. That is, the attempt to add it to set2 will only be made if it was not yet contained in set1.
EDIT: Now, reading the question again, it seems that this was exactly what you intended. So I think that the anser https://stackoverflow.com/a/21755051 by Mustafa Genç is the relevant here
Usually, you should write clearly what you want to do
boolean wasNotContainedInSet1 = set1.add(x);
boolean wasNotContainedInSet2 = set2.add(x);
boolean wasNotContainedInAnySet =
wasNotContainedInSet1 | wasNotContainedInSet2;
or
boolean wasNotContainedInSet1 = set1.add(x);
if (!wasNotContainedInSet1) {
set2.add(x);
}
or whatever...