I suppose this is more a question about language theory than anything else. Why is the first statement in main legal, when the second is not? Don't they evaluate to be the same thing?
public class Main {
public static void main(String[] args) {
foo();
0;
}
public static int foo(){
return 0;
}
}
Java restricts the types of expressions that are allowed in so-called "expression statements". Only meaningful expressions that have potential side effects are allowed. It disallows semantically meaningless statements like 0; or a + b;. They're simply excluded from the language grammar.
A function call like foo() can, and usually does, have side effects, so it is not a meaningless statement. The compiler doesn't deeply inspect the body of foo() to check whether it actually does anything. Calling a function can have side effects, so it is syntactically valid.
This reflects a philosophical difference between C/C++ and Java. Java prohibits various constructs which result in dead or meaningless code.
return;
foo(); // unreachable statement
C and C++ are relatively laissez faire about it all. Write whatever you want; they don't have time to babysit you.
Quoting from the Java Language Specification, §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.
Execution of the expression statement completes normally if and only
if evaluation of the expression completes normally.
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.
In the first statement you are actually calling a function and second statement doesn't give any value. Incase you want to process the return value, you need to call a variable for return type
Eg:
public class Main {
public static void main(String[] args) {
int n = foo();
//do whatever you want with return
}
public static int foo() {
return 0;
}
}
Related
I suppose this is more a question about language theory than anything else. Why is the first statement in main legal, when the second is not? Don't they evaluate to be the same thing?
public class Main {
public static void main(String[] args) {
foo();
0;
}
public static int foo(){
return 0;
}
}
Java restricts the types of expressions that are allowed in so-called "expression statements". Only meaningful expressions that have potential side effects are allowed. It disallows semantically meaningless statements like 0; or a + b;. They're simply excluded from the language grammar.
A function call like foo() can, and usually does, have side effects, so it is not a meaningless statement. The compiler doesn't deeply inspect the body of foo() to check whether it actually does anything. Calling a function can have side effects, so it is syntactically valid.
This reflects a philosophical difference between C/C++ and Java. Java prohibits various constructs which result in dead or meaningless code.
return;
foo(); // unreachable statement
C and C++ are relatively laissez faire about it all. Write whatever you want; they don't have time to babysit you.
Quoting from the Java Language Specification, §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.
Execution of the expression statement completes normally if and only
if evaluation of the expression completes normally.
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.
In the first statement you are actually calling a function and second statement doesn't give any value. Incase you want to process the return value, you need to call a variable for return type
Eg:
public class Main {
public static void main(String[] args) {
int n = foo();
//do whatever you want with return
}
public static int foo() {
return 0;
}
}
NOTICE: This question is not about "Java do not have pointers"
In C language, the code identifier1 * identifier2 is ambiguous for two possible meaning:
If the identifier1 is a type, then this might be a pointer declaration.
If the identifier1 is a variable, then this might be a multiply statement.
The problem is that I cannot choose the right production when building the Syntax tree. I checked Clang's code and it seems that Clang has to put the type checking(by using a symbol table) to the parsing phase(correct me if I'm wrong).
Then I checked the code of javac(OpenJDK), it seems that on parsing phase, there's no semantic analysis involved. The parser can build an AST barely using the tokens.
So I'm curious if Java has the same ambiguous syntax problem? The problem that if the parser don't know an identifier's type, it can not choose the right production?
Or more generic, Does Java has syntax ambiguous that a parser cannot choose a production without other information more than a token stream?
Tokenization is always context sensitive, for languages. However Java does not have operators that are this sensitive. You can, however chain tokens in such a way, that it produces ambiguity, but not only as part of a larger syntactical statement:
A < B
can be part of both public class A < B > { ... } or if (A < B) { ... }.
The first is a generic class definition, the second is a comparison.
This is just the first example from the top of my hat, but I presume there are more.
However, the operators are usually very narrowly defined, and cannot (as in C/C++-like languages) be overloaded. Also, other than in C/C++ there is only one accessor-operator (the dot: .), with one exception (since Java 8, the double-colon ::).
In C++ there are a bunch, so it is much less chaotic.
To the specific question about whether Java is always syntactically decidable:
Yes. A well-implemented compiler can always decide what token is present, depending on a token stream.
I don't think so Java has this problem as Java is strongly typed.
Also, Java does not support Pointers so there is no chance of the above issue.
I hope this answer your question.
Your question cannot be answered easily; this depends on the production rules you have. You say:
there's two production:
<pointer> ::= * {<type-qualifier>}* {<pointer>}?
or
<multiplicative-expression> ::= <multiplicative-expression> * <cast-expression>
But this is not the only possible parser!
With C when looking at
foo * bar;
which could either be a pointer called bar to type foo or the multiplication of foo with bar can be parsed to the token stream:
identifier_or_type ASTERISK identifier_or_type SEMICOLON
and the rest is up to the parser "business logic". So there is no ambiguity at parser level at all here, the logic behind the rule makes the difference between the two cases.
An expression like foo.bar.bla.i can not be parsed in a meaningfull way using the syntax alone. Each of foo, bar and bla can be either part of the package name, a static variable (this one does not apply to foo), or the name of a inner class.
Example:
public class Main {
public static void main(String[] args) {
System.out.println(foo.bar.bla.i);
}
}
package foo;
public class bar {
public static class bla {
public static int i = 42;
}
// public static NotBla bla = new NotBla();
public static class NotBla {
public static int i = 21;
}
}
This will print either 21 or 42 when the static variable bla is commented out or not.
I'm trying to shift from C++ to Java.
What I wonder is, in C++, after a class definition, a semicolon (;) is required, but in Java it isn't.
That is, in C++:
class Person {
public:
string name;
int number;
}; // Note this semicolon
But in Java:
class Person {
public String name;
public int number;
} // Semicolon is not required
That's fine, I understand that.
However, my problem is:
Java also works when I add semicolon at end of class definition, like:
class Person {
public String name;
public int number;
}; // Now this semicolon is confusing me!
I've compiled and executed both the program snippets shown for Java, and they both work. Can anyone explain why this is so? What does the semicolon at the end of a class definition in Java stand for?
I'm sorry if this question is of low quality, but I really need clarification for this. I hope experts in Java will help me.
Well, I've already seen Semicolons in a class definition and other related questions.
Thanks in advance.
I've compiled and executed both the program snippets shown for Java, and they both work. Can anyone explain why this is so?
It is allowed because the Java Grammar says it is allowed; See JLS 7.6.
What does the semicolon at the end of a class definition in Java stand for?
Nothing. It is optional "syntactic noise".
The JLS explains it as follows:
Extra ";" tokens appearing at the level of type declarations in a compilation unit have no effect on the meaning of the compilation unit. Stray semicolons are permitted in the Java programming language solely as a concession to C++ programmers who are used to placing ";" after a class declaration. They should not be used in new Java code.
(Note that this is NOT an "empty statement". An empty statement (JLS 14.6) appears in a syntactic context where a statement is allowed. The presence of an empty statement can change the meaning of your code; e.g. if (a == b) ; c(); versus if (a == b) c();)
In the early days, allowing this was one of the ways in which Java was made more familiar to C/C++ programmers. This familiarity was important to the adoption of Java.
Here's how it works syntactically.
After a top-level class, it works because a compilation unit contains this sequence, according to JLS 7.3:
CompilationUnit:
PackageDeclaration(opt) ImportDeclarations(opt) TypeDeclarations(opt)
And a type declaration is any one of the following, according to JLS 7.6:
TypeDeclaration:
ClassDeclaration
InterfaceDeclaration
;
After a member class, nested in some other class, it works because a semicolon can be a class member declaration, according to JLS 8.1.6:
ClassMemberDeclaration:
FieldDeclaration
MethodDeclaration
ClassDeclaration
InterfaceDeclaration
;
After a local class, inside a method, it works because a semicolon can be an empty statement, according to JLS 14.6:
EmptyStatement:
;
Java added this just for persons like you who switch from C++!
In Java, a single semicolon is a declaration that may be written almost everywhere. Its only purpose is to ease the transition from such languages.
For example, also the following is correct in Java:
;;;;;;;;;;
class X{
;;;;;;;;;;;;;;
} ;;;;;;;;;;;;;;;
A semicolon is simply treated as an empty declaration that does nothing.
Here is a quote from the spec, paragraph 7.6:
Extra ";"
tokens appearing at the level of type declarations in a compilation
unit have no effect on the meaning of the compilation unit. Stray
semicolons are permitted in the Java programming language solely as a
concession to C++ programmers who are used to placing ";" after a
class declaration. They should not be used in new Java code.
So as you see, this is really just for guys like you :).
You can even use a line of semicolons as a nice visual separation. However, I strongly advise against this. But it might be good for bragging purposes. E.g.:
class X {
// Member variables
private int i;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
// Constructors
X(){}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
// Methods
void foo(){}
}
I think this is a followed style which inherites from C:
struct A
{
unsigned a;
unsigned b;
};
Or you can use:
struct A
{
unsigned a;
unsigned b;
}A1,A2;
I'm not familiar with Java, but the reason why there's an extra semicolon needed is because you can define an anonymous class, inside functions. For instance:
void routine(const int x, const int y)
{
class { public: int x; int y; } my_instance;
my_instance.x = x;
my_instance.y = y;
// ... etc
}
You'll usually see this more with structs than with classes, to capture some important variables of a big class.
void f(const BigClass& big_class)
{
struct { std::string str; int i; } props;
props.str = big_class.GetFilename();
props.i = big_class.GetID();
// etc...
}
In the Java DOM/AST (http://help.eclipse.org/indigo/topic/org.eclipse.jdt.doc.isv/reference/api/org/eclipse/jdt/core/dom/package-tree.html) why does an Initializer contain a Block and why is a MethodInvocation an Expression and not a Statement?
I mean, given the code
int a = Integer.parseInt("1");
the ASTView plugin shows me only INITIALIZER > MethodInvocation
Can there ever be an Initializer that really has a Block element?
Moreover, if I have a method like this
public void thisMethod(){
System.out.println();
}
MethodInvocation is wrapped into an ExpressionStatement. But why isn't MethodInvocation a Statement? Just a simple System.out.println() is a valid "Statement". An Expression in the sense of the Java DOM/AST lacks the ability to stand for itself.
Maybe I just didn't the get the whole idea of the separation between Expression and Statement.
The AST tree is designed to reflect the syntax rules of the programming language.
Syntactically, an Initializer consists of a block with an optional static modifier before it. So it’s the most natural implementation having an Initializer class consisting of a Block and modifiers (inherited from BodyDeclaration). So I don’t understand why you question it.
Example of initializers:
class Foo {
static {
System.out.println("static initializer");
System.out.println("class Foo now initialized");
}
{
System.out.println("instance initializer");
System.out.println("an instance of Foo has been created");
}
}
Expressions and statements are two different syntactic constructs. There are places where only either an expression or a statement is allowed. But there are constructs like method invocations which are Expression Statements which means the can fulfill both roles, Expression and Statement. They can be invoked stand-alone for their side-effects but also at places where a value is required.
But since Java does not allow multiple inheritance you cannot create an AST class ExpressionStatement inheriting from both Expression and Statement. So you need a solution like in the Eclipse AST where ExpressionStatement inherits from one and wraps the other. The decision which one to inherit and which one to wrap is easy: you can create a Statement implementation (subclass) which drops the result of the Expression it has wrapped but you cannot create an Expression implementation which provides a result for a Statement that provides no result through its interface. An alternative to such an implementation would be the use of interfaces.
I have question about JIT optimization.
I compiled a simple piece of code:
class btest
{
static final boolean flag=false;
public final void foo(int x)
{
if(flag) {a=x; b=x*2; c=x*3;}
}
public void bar(int y) {foo(y);}
int a,b,c;
};
flag is set to false so foo() is perfectly compiled to empty code - just returns.
But bar() still calls it.
Is it possible that JIT will eliminate this call?
Does it matter if flag belongs to external class?
regards
It can eliminate it and inline it in code.
Note: It can also do this for non-volatile non-final variables where it thinks the thread doesn't change the value. A common mistake is something like
boolean running = true;
public void run() {
while(running) {
// do something
}
}
public void stop() {
running = false;
}
A common misconception is that the thread might keep running for an while but stop at some unknown point, when actually the JIT might inline running and never stop.
The JIT compiler would most likely be able to eliminate this.
But actually, I think that the if statement is likely to be optimized away before then. The reason is in JLS 14.21 starting at the point where is says this:
"However, in order to allow the if statement to be used conveniently for "conditional compilation" purposes, the actual rules differ."
If goes on to say that that the compiler (that is the bytecode compiler!) may generate different code in your example depending on the known value of the condition at compile time.
Note that this special treatment only applies to if statements, and only if the condition is a constant expression. (That term has a very specific meaning - see JLS 15.28) If you tried the same "trick" with a while loop for example, you would get a compilation error complaining about unreachable code.
(This "conditional compilation" special treatment goes back to the early days of Java, and is part of the rationale for Gosling et al's decision to not include a preprocessor in the Java language.)