non-braces if block variable definition gives an error - java

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.

Related

JAVA Not a statement with ?: if statement

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.

Why is the Java compiler giving the incoherent ".class expected" compile error?

If I have a piece of code like this:
public class ABC {
public static void main(String[] args) {
if (true)
int a = 0;
}
}
When I compile it, Java compiler produces an error
.class expected.
I know that when we don't use braces, we can use only one statement after if.
And I also know that I will not be able to use the int variable a, because as soon as the ; is encountered, the program comes out of if, and the variable a loses it's scope.
I am not surprised that this code emits an error, but why is the error message '.class' expected?
What is Java compiler trying to say?
I suspect the problem is that the only token sequence that can legitimately follow the keyword token of int in this case is . followed by class. The declaration statement you've got at the moment isn't valid because a local variable declaration on its own isn't a Statement as per JLS 14. (It's a BlockStatement.)
Note that in the tutorialspoint environment referenced in the comment, if you use a class instead of int, a different error is produced - potentially because the set of valid tokens is different in that scenario. (String.getClass(); would be valid for example, whereas int.getClass(); wouldn't.)
There is a valid question asked in a comment:
Why this .class thing? If you know any situation in which int followed by .class can compile, then please tell me.
And that's easy - you can call a method on the Class reference returned by int.class:
public class ABC
{
public static void main(String args[])
{
if(true)
int.class.getName();
}
}
That's not useful code, but it is valid code. It compiles for me without warnings or errors.
As mentioned in comments, more recent compiler versions give more useful errors - I would recommend upgrading.
As opposed to what some commenters say, this code can actually produce that error.
int a = 0;
^
According to the Java Language Specification, a variable declaration needs to be in a code block:
Every local variable declaration statement is immediately contained by a block. Local variable declaration statements may be intermixed freely with other kinds of statements in the block.
I assume you already knew that.
But why the .class expected error?
The reason why the exception says .class expected, is compiler specific. Other compilers will emit not a statement or illegal start of expression.
My guess is that it is related to the way the compiler evaluates the code. The only way int can be valid at that location, is when followed by .class. So as soon as the token int is detected, the compiler expects it to be followed by .class.
For example,
if (true)
int.class.getFields();
would be a valid statement.
So the compiler gives an error that is in some way logical, that is, .class expected.
Other compilers probably evaluate the whole statement as a variable declaration, rather than separate tokens like int, a, = and 0.
Specific compiler
I do not know which specific compiler tutorialspoint.com is using, but their javac version (using javac -version) is javac 1.7.0_75 on Fedora release 21 (Twenty One) (using the command cat /etc/issue.net).
PS: I don't know if you have a specific reason for using the compiler of which you posted an image, but I suggest you start using Eclipse or Netbeans.

Compilation error on While(scan.hasNext()), it says "; expected"

I'm getting an error off of a segment of code which came from this forum.
While(scan.hasNext()) {
}
It says
';' expected
Please direct me in the right direction.
Your issue is that you've used 'While' instead of 'while' (it's case sensitive).
Your IDE has recognised that the method While doesn't exist, and has created it (unimplemented). It thinks that While is a method, makes that method, and then expects it to have the syntax of that method - of course, "while" is a construct and has a different syntax.

When is an unassigned expression a valid 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.

Why can't you create a 1 statement function without curly braces?

So, in most programming language, if you are using a loop or an if, you can do it without curly braces if there is only a single statement in it, example:
if (true)
//Single statement;
for (int i = 0; i < 10; i++)
//Single Statement
while (true)
//Single statement
However, it doesn't work for functions, example:
void myFunction()
//Single Statement
So, my question, why doesn't it work for functions?
C++ needs it to disambiguate some constructs:
void Foo::bar() const int i = 5;
Now does the const belong to bar or i ?
Because language grammar forbids you to do that.
The Java grammar defines a method as following:
MethodDeclaration:
MethodHeader MethodBody
Methodbody as:
MethodBody:
Block
;
Which means either a Block (see below) or a single semicolon
Block:
{ BlockStatementsopt }
And a block as one or more statements within curly brackets.
However an if is defined as:
IfThenStatement:
if ( Expression ) Statement
Where no block is needed after the closing ) and therefore a single line is ok.
Why they chose to define it that way? One can only guess.
Grammar can be found here: http://docs.oracle.com/javase/specs/jls/se7/html/index.html
This is not a rule, in some languages you can (Python? Yes, I know that's really contrived example :)) ), in other you cannot.
You could very well extend your question for example to class and namespaces, for example, why not:
namespace Example
class Foo : public Bar
public: std::string myMethod()
return "Oh noes!";
right? At each level, that's just a single item, so why not skip the braces everywhere?
The answer is at the same time simple and complex.
In simple terms, it's about readability. Remember that you can layout your code as you like, since whitespaces are usually discarded by the compiler:
namespace Example class Foo : public Bar public: std::string myMethod() return "Oh noes!";
Well, that starts looking unreadable. Notice that if you add the braces back
namespace Example { class Foo : public Bar { public: std::string myMethod() {return "Oh noes!";}}}
then it, strangely, becomes somewhat comprehensible.
The actual problem is not readability (who cares anyways? I'm joking of course) but in the latter: comprehension. Not only you must be able to comprehend the code - the compiler must. And for the compiler there is no such thing as "oh, this looks like function". The compiler must be absolutely sure that it is a function. Also, it must be completely sure about where it starts, where it ends, and so on. And it must do that without looking at whitespaces too much, since C-family languages allow you to do add them in any quantities you like.
So, let's look again at the packed-up no-braces example
namespace Example class Foo : public Bar public : std::string myMethod() return "Oh noes!";
^ ^ ^^
I've marked some problematic symbols. Assuming you could define a grammar that handles it, please note how the meaning of ":" character changes. At one time it's denoting that you're specifying inheritance, at other point it's specifying access modifier to a method, at third place it's just namespace qualifier. Ok, the third one could be discarded if you were smart and noticed it's actually '::' symbol, not just a ':' character.
Also, meaning of keywords can change:
namespace Example class Foo : public Bar public : std::string myMethod() return "Oh noes!";
^^^^^^ ^^^^^^
At first place, it defines access modifier for inherited base class, at second place it defined access modifier for a method. What's more, at first place it's not meant to be followed by a ":" and at second place it's required to be followed by it!
So many rules, exceptions and corner cases, and we covered just 2 simple things: public and ':'. Now, imagine you are to specify the grammar for the whole language. You describe everything in the way you'd like to have. But, when you gather all the rules together, they at some point may start overlap and collide with each other. After adding Nth rule, it may happen that your 'compiler' would be unable to tell whether the 'public' actually marks inheritance, or starts a method:
namespace Example class Foo : public ::Bar public : std::string myMethod() return "Oh noes!";
^^^^^^^^ ^^^^^^^^
Note that I only changed the Bar to ::Bar. I only added a namespace qualifier, and now our rule of "public is followed by a colon" is trashed. As I now added a rule that "base class names may have namespace qualifiers", I also must add more rules to cover yet another corner cases - to remove the ambiguity of the meaning of "public" and ":" in this place.
To cut the long talk: the more rules, the more problem you have. The "compiler" grows, gets slower, eats more resources to work. This results in inability to handle large code files, or in frustration when the user must wait oh-so-long for that module to compile.
But what's worse for the user is, the more complex or ambiguous, the worse error messages are. Noone wants to use a compiler that is unable to parse some code and also unable to tell you what's wrong with it.
Remember in C++ what happens when you forget some ';' in a .h file? Or when you forget some }? Compiler reports you an error 30 or 300 lines farther. This is because the ';' and '{}' can be ommitted in many places, and for that 30 or 300 lines, the compiler simply does not yet know that's something wrong! Were the braces required everywhere, the point of error could be pinpointed faster.
The other way: making them optional at namespace, class, or function level, would remove the basic block-starts/block-ends markers and, at least:
could make the grammar ambiguous (and hence force to add more rules)
could hurt detecting (and reporting!) errors
any part of which noone really wants.
The C++ grammar is so complex, that it actually might be not possible to omit the braces at those places at all. For Java or plain C, I think it could be possible to make a grammar/compiler that would not require them, but would it would still hurt error reporting much. Especially in C which allows to use #include and macros. In early Java, the impact might be lesser, as the grammar is relatively simple, compared i.e. to current C++..
Probably the simplest, fastest, easiest to implement, and probably easiest to learn grammar would .. require braces (or any other delimiters) just about everywhere. Check LISP for example. But then, large part of your work would consist of constantly writing the same required markers, which many language-users simply does not like (i.e. I get nauseous when I need to work on some old code in VisualBasic with its "if then end if" yuck)
Now, if you look at brace-less language like Python - how does they solve it? They denote the block-starts/block-ends by .. intendation. In this language you must indent your code properly. If you don't indent it correctly, it will not compile at all, or it the loops/functions/etc will silently get their code messed up, because the compiler will not know what part does belong to which scope. No free lunch here again.
Basically a method(function) is a collection of statements that are grouped together to perform an operation. We group the statements for reusable. That is if you know that a set of instructions will used often in that case we create it as a separate function.
If you can perform the task in a single line of code, then why do you need to write a function?
Because the grammar of the language doesn't allow you to.
Here is the grammar for a function in C taken from the ISO/IEC 9899-1999 specification:
6.9.1 Function definitions
Syntax
1 function-definition:
declaration-specifiers declarator declaration-listopt compound-statement
The compound-statement part is the body of a function, and a compound statement is declared as
compound-statement:
{ block-item-listopt }
i.e. it starts and ends with braces.
An if, while or similar body can have a statement as its body.
(6.8.5) iteration-statement:
while ( expression ) statement
A statement can be one of several constructs.
statement:
labeled-statement
compound-statement
expression-statement
selection-statement
iteration-statement
jump-statement
of which only compound-statement requires the braces.
In c++ you need a compound statement to make a function body - which is actually surrounded with curly barces. It does not mean you need to have curly braces right immediately, following will compile just fine:
int foobar()
try {
return 1;
}
catch (...){return 0;}
You can't precisely say there are no one statement functions in C#. Anonymous methods could be one of them. Without single line statements we could not have Lambda expression in c#. The C# 3.0 wouldn't be exist.
There is no reason to add that extra parsing code in the compiler because the functionality is really useless, how many one line methods have you written that are not accessors or mutators? This has been dealt with in C# via properties but not yet in Java.
So the reason is, it's unlikely to be used considering most developers discourage leaving out optional bracket blocks anyway.

Categories

Resources