Today, after half an hour of searching for a bug, I discovered that it is possible to put a semicolon after an if statement instead of code, like this:
if(a == b);
// Do stuff
Which basically means that the stuff will be done whether a
equals b
or not, and the if
statement has no point whatsoever. Why doesn't Java give me an error? Is there any situation in which this would be useful?
发布评论
评论(18)
为什么会发生?
java语言规范
It essentially means that you want to execute empty statement if a==b
What should you do:
There are two main solutions to this problem:
You can avoid problems with empty statement by using code格式化
{和} 中的周围内容 。这样做
您的空语言将更可读。
您还可以检查用于静态代码分析的工具,例如:
他们可以立即突出此类问题。
我建议将这两种解决方案结合起来。
Why does it happen?
Java Language Specification says that:
It essentially means that you want to execute empty statement if a==b
What should you do:
There are two main solutions to this problem:
You can avoid problems with empty statement by using code formatter
and surrounding stuff inside
if
with{
and}
. By doing thisYour empty statement will be much more readable.
You can also check tools used for static code analysis such as:
They can instantly highlight problems such as this one.
I would recommend to combine both solutions.
有用?如“使您的代码更清洁,更清晰,更快,更可维护”?一点也不。这很可能很差,令人困惑的代码。
,但不一定是良性。由于方法会导致副作用,因此可以执行动作和/或更改状态,并可以选择评估 Short-short--操作员的电路。
在这里,
a()
或b()
可能会做某事,b()
仅在a()才能执行代码>是正确的。
至于为什么,我认为答案仅仅是偏离定义的预期行为会更糟(例如
之类的语句while(reader.read());
)而不是编写不良代码的开发人员的替代方案。编写不良代码总是可能的。只是要重申,这几乎在任何情况下都是不好的代码。
Useful? As in "makes your code cleaner, clearer, faster, more maintainable"? Not at all. This is most likely poor, confusing code.
But it's not necessarily benign. Such a statement can perform actions and/or alter state due to methods which cause side effects, and optionally evaluate those methods due to short-circuiting of operators.
Here,
a()
orb()
may do something, andb()
will only execute ifa()
is true.As to why, I think the answer is simply that it would be worse to deviate from defined, expected behavior (e.g. statements like
while(reader.read());
) than the alternative of developers writing bad code.Writing bad code is always possible. And just to reiterate, this would be bad code in almost any case.
可能的用例:
不好,但可能。
尽管如此,我确实认为,如果,Java规范应该禁止空
。
A possible use case:
Not good, but possible.
Still, I do think that the Java specification should disallow an empty
if
.如果您使用的是Eclipse,则可以警告您有关这些陈述的信息:
If you're using Eclipse, you can make it warn you about those statements:
如果使用语句使用
,则如果条件为真,则将执行
之后的第一个语句。如果您在(带卷曲括号)之后有一个块,则对整个块很重要。如果没有块,则仅计算一个语句。单个半龙是一个空的语句。您也可以从您的示例中编写代码:If you use an
if
statement, the first statement after theif
will be executed if the condition is true. If you have a block after theif
(with curly braces), it counts for that whole block. If there is no block it counts for only one statement. A single semicolon is an empty statement. You could also write the code from you example like this:这是从句法有更多的句法糖与陈述区分表达式的日子。
基本上,逗号用作列表项目分离器,因此将半隆用作“语句列表”分隔符。缺点是在列表中处理空项目的处理以及块中的null语句。
在项目列表中,Java使用明确的关键字
null
,但是“ null语句”只是一个空行。允许存在空线是从C继承的传统中保留了C。为什么这样做?特别是使用 语句时,当您知道没有执行任何语句时:因为某些语句具有副作用:
是的,这不是最好的例子,但基本上它说从流中读取字节什么都不做。在某些角落情况下可能很有用,但是即使此示例不是最好的,它也说明了意图。我们希望在不小心执行任何陈述的情况下感受表达的副作用。
It is an old leftover from the days when there was more syntactic sugar to differentiate expressions from statements.
Basically, the comma was used as the list item separator, so the semicolon was used as the "list of statements" separator. The downside is in the handling of null items in lists, and null statements in blocks.
In a list of items, Java uses the explicit keyword
null
, but a "null statement" is just an empty line. Allowing the existence of an empty line is a holdover from tradition inherited from C.Why do it? Especially with an
if
statement when you know that no statements are being executed: Because some if statements have side effects:Yes, it is not the best example, but basically it says read a byte from the stream and do nothing. Might be useful in some corner cases, but even if this example isn't the best, it illustrates the intent. We want to feel the side-effects of the expression without accidentally executing any statements.
我想不出有用的场合。 在IDE中使用代码格式之类的循环可能很有用
它对于诸如循环或
,这些错误变得很明显。有些IDE也将其强调为可能的错误。
I can't think of an occasion where it is useful. It can be useful for loops like
or
If you use your code formatting in your IDE regularly these sort of bugs become obvious. Some IDEs highlight this as a probable bug as well.
我同意您的看法,对于人类来说,这没有任何有用的目的。我怀疑它在那里,因为它简化了语言定义。这意味着在 e上与 while 时的事物相同的事物。
I'd agree with you there's no useful purpose to this for a human. I suspect it's there because it simplifies the language definition; it means that the thing that comes after an
if
is e same as the thing that comes after awhile
, for instance.Java允许一个空块任何位置允许语句块。我敢肯定,将此作为所有块的一般规则简化了编译器。
我同意这主要是造成很难找到的错误的原因。即使有一个语句,我也总是在块周围使用牙套,但是Java允许您在任何时候都用牙套制作一个块,因此使用牙套无法将您从这种命运中保存下来。例如,我曾经浪费了4个小时尝试找到这样的东西:
第一行末尾的半隆是错字,意外地将声明块用于时循环空的。由于语法有效,因此编译并运行良好,只是我想要的方式。确实很难找到。
我可以想到一种情况,即非常好,您可以拥有空块,这是这样的:
在上面的示例中,您希望能够分开各种条件。请记住,这些条件可能是重叠的,因此并非总是可以重新安排订单。如果其中一个条件确实不需要任何事情,那么Java允许您拥有一个空块是很好的。否则,当您真的不想完成任何操作时,该语言将需要某种形式的“ NOOP”方法。
我个人更喜欢明确的“ NOOP”语句 - 但这不是Java的定义方式。
Java allows an empty block any place a statement block is allowed. I am sure making this a general rule for all blocks simplifies the compiler.
I agree that this is primarily the cause of bugs that are spectacularly hard to find. I always use braces around blocks, even when there is a single statement, but Java allows you to make a block with braces at any point, so using braces can not save you from this fate. For example, I once wasted 4 hours trying find something like this:
The semicolon at the end of the first line was a typo, accidentally making the statement block for the while loop empty. Because the syntax is valid the program compiled and ran fine, just not the way I wanted it to. It was really hard to find.
I can think of one situation where it is very nice that you are allowed to have empty blocks, and this is something like this:
In the above example, you want to be able to separate out various conditions. Remember, those conditions might be overlapping, so it is not always possible to rearrange the order. If one of the conditions really does not need anything done, then it is nice that Java allows you to have an empty block. Otherwise, the language would need some form of a "noop" method to use when you really do not want anything done.
I personally would prefer the explicit "noop" statement -- but that is not how Java is defined.
为什么?这是因为编译器作家更容易。 if if if code>之后,您无需提出特殊情况
如果(cond),即使允许它实际上是一个可怕的想法, 。允许更容易,然后添加一个案例检查此问题。
Why? It's because its easier for compiler writers. You don't have to make a special case to check for semicolons after
if(cond)
and has an added usage of allowingEven though it's actually a terrible idea to allow this. It's just easier to allow and then to add a case to check this.
Just a FYI about the usability and what difference it makes or can make if there is a statement like that
Consider a piece of code like the following.
显然,在这种情况下,如果语句确实会更改输出,则
。因此,这样的陈述可以有所作为。
在这种情况下,这可能有用或更好地说对程序产生影响。
Just a FYI about the usability and what difference it makes or can make if there is a statement like that
Consider a piece of code like the following.
Clearly in this case, the
if
statement does change the output. So a statement like that can make a difference.This is a situation where this could be useful or better to say have an impact on program.
A few definitions from the jls explain this (chapter 14):
Blocks are Statements
As stated
The if-clause
Though this is as well the case for
for
andwhile
-loops, I'll useif
-statements.这些规则几乎相同。if-statement
的句法描述可以找到在这里。因此我们可以在这里使用块。
但是为什么它与之搭配; ?
;
定义为emptystatement
( link ),也是statement noshortif
。因此,在有条件的代码中,例如If-Statement
和loops,我们可以用block
emptyStatement
,如果statement> statement> statement nonoshortif
或语句
是必需的。因此,
如果(表达式)emptyStatement
有效。为什么这不给错误?
非常简单:如果Java找到无效的语法,Java会出现错误。但是
如果(表达式)emptyStatement
是完全有效的语法。而是javac
使用适当的参数启动,会发出警告。 为此,列出了警告名称空
。因此,使用-Xlint进行汇编:ALL
或-Xlint:empty
将对此发出警告。您的IDE也应该可以选择此类警告。
对于Eclipse,请参见@nullptr的答案。 In IntelliJ, you can press
Ctrl + Shift + A
, enterempty body
into the search field and enable the warning (marked in the image)What is this even used for?
老实说,从简约的角度来看,它没有太多用途。通常有一种方法可以在没有“无所事事”命令的情况下完成工作。 It's rather a question of personal preferences, whether you rather use
or
and same would apply to other cases, in which the
EmptyStatement
is used.在此主题上要考虑的一个重要点是代码的可读性。在某些情况下,使用NO-OP可以更易读代码。另一方面,在某些情况下,使用emptyStatement
- 上面的示例将计算到以后的IMO中,代码变得更加困难。A few definitions from the jls explain this (chapter 14):
Blocks are Statements
As stated here, a
Block
is aStatementWithoutTrailingSubstatement
, which in turn is aStatementNoShortIf
, which is aStatement
. Thus where ever any of these is required, we can insert aBlock
.The if-clause
Though this is as well the case for
for
andwhile
-loops, I'll useif
-statements. These rules are pretty much the same. The syntactical description ofif-statements
can be found here.So we can use our block here.
But why does it work with ; ?
;
is defined as theEmptyStatement
(link), which is as well aStatementNoShortIf
. So in conditional pieces of code, likeif-statement
and loops, we can replace aBlock
with aEmptyStatement
, if aStatementNoShortIf
orStatement
is required.Thus
if(Expression)EmptyStatement
works.Why doesn't this give an error?
Pretty simple: java gives an error if it finds invalid syntax. But
if(Expression)EmptyStatement
is perfectly valid syntax. Insteadjavac
gives a warning if launched with the proper parameters. The full list of warnings that can be dis-/enabled lists the warning-nameempty
for this purpose. So compilation with-Xlint:all
or-Xlint:empty
will generate a warning about this.Your IDE should have an option to enable this kind of warning as well.
For eclipse, see @nullptr's answer. In IntelliJ, you can press
Ctrl + Shift + A
, enterempty body
into the search field and enable the warning (marked in the image)What is this even used for?
To be honest, there's not much use in it from a minimalistic point of view. There's usually a way to get things done without a "do nothing" command. It's rather a question of personal preferences, whether you rather use
or
and same would apply to other cases, in which the
EmptyStatement
is used. An important point to consider on this topic is readability of code. There are occasions, where code becomes more readable by using the no-op. On the other hand there are cases, where code becomes quite a lot harder to comprehend with using theEmptyStatement
- the above example would count to the later IMO.您可以使用IF语句,没有
{}
如果仅执行一行,则使用,如果(a == b);
您是在说如果他们说如果他们平等,执行和空语言...因此,它无能为力,然后在IF块之外返回您的普通循环。You can use an IF statement without
{}
if there is only a single line to be executed, so by usingif(a==b);
you are saying if they equal, execute and empty statement... So it will do nothing, and then return to your normal loop, outside of the IF block.我可以想到一个需要一个空语句的方案(不是条件,而是 while 循环)。
当程序只希望从用户进行明确确认时。当用户确认之后的工作取决于其他一些内容,并且用户希望控制何时继续进行时,可能需要这是必需的。
I can think of a scenario where an empty statement is required (not for
if
condition but forwhile
loop).When a program just want an explicit confirmation from the user to proceed. This may be required when the work after the user confirmation depends on some other things and user want to take control of when to proceed.
看一下:
因此,您可以这样写:
但是,如果此代码是这样的:
您可以这样写:
因此,如果(a!= b); 注意,您会知道
look this:
so, you can write like this:
but,if this code is this:
you can write like this:
so,you will know
if(a != b);
do notingIF中的半彩词指示终止IF条件(如Java
;
中)作为语句的结尾,因此在执行后的语句。The semi-colon in the if indicates the termination of the if condition as in java
;
is treated as the end of a statement, so the statement after if gets executed.结束时的分号
if(a == b);只需单行完成语句,这意味着忽略条件的结果,然后继续从下一行执行
此代码很有用,另一方面,有时会在程序中介绍错误,例如
案例1.
a = 5;
B = 3;
如果(a == b);
prinf(“ A和B是平等的”);
案例2。
a = 5;
B = 5;
如果(a == b);
prinf(“ A和B是平等的”);
将在屏幕上打印相同的输出...
Semicolon at the end of,
if(a==b); simply finish the statement in single line which means ignore the result of condition and continue the execution from the next line
This code is useful, on the other hand sometime introduce bug in program, for example,
case 1.
a = 5;
b = 3;
if(a == b);
prinf("a and b are equal");
case 2.
a = 5;
b = 5;
if(a == b);
prinf("a and b are equal");
would print the same output on the screen...
在研究课堂的编程分配时,我正在与doodads的n网格一起工作,并将随机doodad的特征与上述,下方,左下和右上方的特征进行比较时,我发现了这一点,以防止嵌套语句和潜在边界异常。我的目标是最大程度地减少代码,并避免嵌套IF-Statement。
其中
方法(doodad a,doodad b)
在a和b之间进行一些操作。另外,您可以使用异常处理来避免使用此语法,但是它对我的应用程序有效。
While working on a programming assignment for class where I am working with a N by N grid of doodads and comparing characteristics of a random doodad to those above, below, left, and right, I found a nice use of this to prevent nested statements and potential boundary exceptions. My goal was to minimize code and keep from nesting if-statements.
where
method(Doodad a, Doodad b)
does some operation between a and b.Alternatively, you could use exception handling to avoid this syntax, but it works and works well for my application.