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.
Related
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.
I write my java code
if(x !=null){
// Do something
}
else {
// Do something
}
Then sonar Qube gives violation. Is the rule really needed for Confusing ternary?
According to the reference link you provided, the rule states:
In a ternary expression avoid negation in the test. For example, rephrase: "(x != y) ? diff : same" as: "(x == y) ? same : diff". Consistent use of this rule makes the code easier to read. Also, this resolves trivial ordering problems, such as "does the error case go first?" or "does the common case go first?".
It might be a bit confusing that the rule is named "confusing ternary rule" because what you have is a regular if-else construct, not a ternary expression. However, since ?: can be thought of as shorthand for an if-else statement, you can also apply the rule here.
Does it makes sense? Personally, I think absolutely. But if it doesn't apply to your (or your company's) coding style and, therefore, you get many violations, I'd rather remove—or adapt—the rule. As the reference says: consistency is important.
This is required cause it's unnecessary causes confusion in first look.
e.g.
if(reporters username is not oliver)
say it's stackoverflow's concern
else
say it's oliver's concern
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.
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...
This question already has answers here:
Ternary Operator
(4 answers)
Closed 5 months ago.
Is there a way to implement this in a ternary operation. I'm very new to that ternary stuff, maybe you could guide me.
if(selection.toLowerCase().equals("produkt"))
cmdCse.setVisible(true);
else
cmdCse.setVisible(false);
This one doesn't seem to work.
selection.toLowerCase().equals("produkt")?cmdCse.setVisible(true):cmdCse.setVisible(false);
In this case, you don't even need a ternary operator:
cmdCse.setVisible(selection.toLowerCase().equals("produkt"));
Or, cleaner:
cmdCse.setVisible(selection.equalsIgnoreCase("produkt"));
Your version:
selection.toLowerCase().equals("produkt")? cmdCse.setVisible(true): cmdCse.setVisible(false);
is semantically incorrect: ternary operator should represent alternative assignments, it's not a full replacement for if statements. This is ok:
double wow = x > y? Math.sqrt(y): x;
because you are assigning either x or Math.sqrt(y) to wow, depending on a condition.
My 2cents: use ternary operator only when it makes your program clearer, otherwise you will end up having some undecipherable one-liners.
Perhaps
cmdCse.setVisible(selection.toLowerCase().equals("produkt"));
The ternary operator isn't exactly like an if statement. A ternary operator has to "return" something from both sides, so putting void method calls like setVisible() there won't work.
Instead, you could do something like this without ternary operators at all:
cmdCse.setVisible(selection.toLowerCase().equals("product"));
But just to demonstrate the point, the ternary equivalent would look something like this:
cmdCse.setVisible(selection.toLowerCase().equals("product") ? true : false);
Notice how now the ternary operator "returns" true or false on both sides instead of simply calling a void method.
I think this will work for you
cmdCse.setVisible(selection.toLowerCase().equals("produkt"));
Directly from the docs
Use the ?: operator instead of an if-then-else statement if it makes your code more readable; for example, when the expressions are compact and without side-effects (such as assignments).
In your case cmdCse.setVisible(true / false); doesn't return anything, and the operation also has side effects (it changes state of cmdCse), so the conditional operator cannot be used here (when you do use the operator, both of the ? and : branches must have the same return type).
As an aside, please note that .. ? .. : .. should be referred to as the conditional operator
On the issue of using exceptions
I want to answer the issue of the exceptions here as this question is a duplicate for another question concerning throwing exceptions from a ternary expression, but this is not addressed in the above answers.
The general consensus is that it cannot be done directly as in:
public Character next() {
return hasNext() ? s.charAt(cur++) : throw new NoSuchElementException(); // compilation error
}
will give you a compilation error, but as Clement pointed out it can be done via a declared extra function. It can also be done via (ab-)using lambda expressions.
public Character next() {
return hasNext() ? s.charAt(cur++) : ((Function<Integer, Character>) x -> {throw new NoSuchElementException();}).apply(1);
}
for sure this is not that pretty (it is pretty ugly) and I would not recommend to do that for readability purposes, but sometimes there are circumstances which might warrant exceptionally doing that. If someones figures out a way to do it without the cast it would be a bit more readable.
If you had a function throwNoSuchElementException() defined somewhere that you use more than once, it would look a bit more readable:
public Character next() {
return hasNext() ? s.charAt(cur++) : throwNoSuchElementException();
}
(P.S.: I included this answer for completeness sake, as I asked myself can it really be not done?)
(P.S.S.: If the exception to be thrown is not a runtime exception this will not work so easily and would require even more handstands - not really worth it)
Here are my tips, if you need to set things to booleans, then simple use setBoolean(condition), else, if you need to set a variable to a non boolean value, then use var=condition?result1:result2(or the variable itself if you don't want to change if condition is false), otherwise, use if else.