Java DOM/AST - why is MethodInvocation an Expression? - java

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.

Related

Is an object created when you pass a method reference in a method

As far as I know, when you define a method in a function, an object is instantiated:
myList.stream().map(x->x.getName().replaceAll('a','b')).toList();
Or the equivalent
Function<MyObject,String> myFunc = x -> {return x.getName().replaceAll('a','b');}
myList.stream().map(myFunc).toList();
x->x.getName().replaceAll('a','b') is created as a functional interface object (and requires memory allocation, a new somewhere/somehow, right?).
However, if I pass an already existing method as a parameter, is anything created?
class A{
public list<String> transform(List<String> input){
return input.stream().filter(this::myFilter).filter(A::staticFilter).toList();
}
public boolean myFilter(String s){ // Whatever }
public static boolean staticFilter(String s) { // whatever }
}
What happens here:
Is myFilter "wrapped" in a functional interface? (is it the same for a static method reference?)
Is there something specific that happens at bytecode level which is not "clear" on language level (like method pointer or something?).
From JavaDoc Api
Note that instances of functional interfaces can be created with
lambda expressions, method references, or constructor references.
As to if the lambda expression will create an instance in heap or not, you can follow this thread where the top comment from #Brian Goetz might be helpful.
About lambda expressions:
Also as indicated here in Java Specifications for Run-Time Evaluation of Lambda Expressions
These rules are meant to offer flexibility to implementations of the
Java programming language, in that:
A new object need not be allocated on every evaluation.
Objects produced by different lambda expressions need not belong to
different classes (if the bodies are identical, for example).
Every object produced by evaluation need not belong to the same class
(captured local variables might be inlined, for example).
If an "existing instance" is available, it need not have been created
at a previous lambda evaluation (it might have been allocated during
the enclosing class's initialization, for example).
So to your question:
x->x.getName().replaceAll('a','b') is created as a functional
interface object (and requires memory allocation, a new
somewhere/somehow, right?).
The answer is some times yes, some times no. Not always the same case.
About method reference expressions:
Evaluation of a method reference expression produces an instance of a
functional interface type (§9.8). Method reference evaluation does not
cause the execution of the corresponding method; instead, this may
occur at a later time when an appropriate method of the functional
interface is invoked.
Based on what is written here for Run-Time Evaluation of Method References
The timing of method reference expression evaluation is more complex
than that of lambda expressions (§15.27.4). When a method reference
expression has an expression (rather than a type) preceding the ::
separator, that subexpression is evaluated immediately. The result of
evaluation is stored until the method of the corresponding functional
interface type is invoked; at that point, the result is used as the
target reference for the invocation. This means the expression
preceding the :: separator is evaluated only when the program
encounters the method reference expression, and is not re-evaluated on
subsequent invocations on the functional interface type.
I would assume that a functional interface type is created but not each time with each invocation. It should as well be cached and optimized for the less amount of evaluations.
Well, the compiler has a lot of leeway in how it actually implements the code you write, but generally .map() takes a Function Object so whatever expression you put in the parentheses will produce an object.
That does not mean, however, that a new Object is created every time. In your lambda example, the lambda function doesn't reference anything defined in an enclosing method scope, so a single Function object can be created and reused for all calls.
Similarly, the A::staticFilter reference only needs to produce one Function.
The object created by this::myFilter, however, needs to have a reference to this (unless the compiler can determine that it doesn't!), and so you will certainly get a new Function created inside each call to transform.

Throwing a LocalVariableDeclarationJava error after changing the linkedlist name [duplicate]

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;
}
}

Lambda Expressions and Non-Class Java Methods [duplicate]

This question already has answers here:
Non-class functions in Java
(4 answers)
Closed 2 years ago.
When declaring methods in Java, do they need to be a part of a class? I am familiar with the idea of a Utility Class:
"Utility Class, also known as Helper class, is a class, which contains just static methods, it is stateless and cannot be instantiated. It contains a bunch of related methods, so they can be reused across the application."
However, can one just create a method separate from any class altogether? (I'd assume scope becomes public by default and declaring anything else for scope might result in an error).
If this is not possible, perhaps that would explain the need for Utility Classes, but I wasn't sure as I hadn't thought about this before - I assumed naturally you could make functions separate from any specific class, but I had been looking through various code samples and couldn't find a specific example where this was occurring.
Part of the reason I am asking this is I was reviewing this article (and mentioned in point 2):
https://www.geeksforgeeks.org/lambda-expressions-java-8/
In it, it states: Lambda expressions are added in Java 8 and provide below functionalities.
1) Enable to treat functionality as a method argument, or code as data.
2) A function that can be created without belonging to any class.
3) A lambda expression can be passed around as if it was an object and executed on demand.
Java is a sort of purely class-based programming language. So, Yes, it and everything needs to be a part of a class.
You are right, you can make a Utility class making methods public static in this way methods can be called without instantiating the class.
Answer to question in the comment:
Why would someone write Object.method() instead of just method()?
Object class is a standard class in java.lang package. You should not create your class named Object otherwise you will need to specify java.lang.Object everywhere you use java.lang.Object.
Now you probably meant
Why would someone write MyUtilClass.method() instead of just method()?
Suppose you have a class MyUtilClass as follows
public class MyUtilClass {
public static int utilMethodA() {
return 1;
}
public static boolean utilMethodB() {
int value = utilMethodA();
if(value == 1)
return true;
else
return false;
}
}
And suppose you have another class MyClass as
public class MyClass {
public void classMethod() {
int value = MyUtilClass.utilMethodA();
}
}
Here if you see in MyUtilClass, utilMethodB() uses utilMethodA() without writing MyUtilClass.utilMethodA() (however, we could write it that way also). Here we did not need to write it as MyUtilClass.utilMethodA() because compiler can find the utilMethodA() without fully specifying it's class because it is present inside it's own class.
Now, In Myclass's myMethod(), we must specify MyUtilClass.utilMethodA() (without it, it won't work), because the compiler has no way of figuring out that you meant to call utilMethodA() of MyUtilClass. There could be hundreds of classes with a method named utilMethodA(), the compiler has no way of finding out which one of the hundred methods you want to call.
Note:-
Also, you can do static import of MyUtilClass.myMethod() like
import static my.package.name.MyUtilClass.myMethodA()
and then use utilMethodA() inside MyClass without prefixing MyUtilClass (but you already informed compile by static import that you will be using utilMethodA() of MyUtilClass right?)
Looks cool to you? No!
This is rather a bad way because
It makes code looks unobvious. In a large class, it may seem that
method utilMethodA() is a local method defined somewhere in
MyClass.
Also, it can generate ambiguity to the compiler if more than one static import of utilMethodA() is done. As compiler has no way of figuring out which of the two you intend to use.
(Edit) Regarding Lambda Expression
Lambda expression is pretty cool stuff added in Java 8. They are basically a kind of function. They provide you the power to define a function right where they need to be used. For example in this link that you provided, see the example shown below syntax of lambda, there the statement
ArrayList<Integer> arrL = new ArrayList<Integer>();
arrL.add(1);
arrL.add(2);
arrL.add(3);
arrL.add(4);
arrL.forEach(n -> { if (n%2 == 0) System.out.println(n); });
Basically, what we are doing here is, we are defining a function, if n is multiple of 2, we print n. We are doing it forEach element of arrL. Did you see, we defined the function to be executed on each element right inside a function call forEach(). That's the beauty of lambda expression.
Now, coming to your question,
So the primary benefit of lambda (besides syntax) is to make it easier to implement functional interfaces (compared to what alternative)?
Yes, sort of. Easy in terms of not creating a separate class implementing the interface and then implementing the abstract method and then calling that implemented method.
This becomes lots of work, especially if you need to call that method only once for example,
Consider the Functional Interface FuncInterface defined as in the link in your question:
interface FuncInterface {
// An abstract function
void abstractFun(int x);
// A non-abstract (or default) function
default void normalFun() {
System.out.println("Hello");
}
}
Now, you want two kind of implementation to your functional interface:
One that provides twice of the passed int x.
Another one that provides square of passed int x.
So, you make two implementations of it:
First FuncInterfaceTwiceImpl
public class FuncInferFaceTwiceImpl implements FuncInterface {
#Override
public void abstractFun(int x) {
System.out.println(2 * x);
}
}
Second, FuncInterfaceSquareImpl as
public class FuncInterfaceSquareImpl implements FuncInterface {
#Override
public void abstractFun(int x) {
System.out.println(x * x);
}
}
Now, you call them as
public class MyClass {
public static void main(String[] args) {
FuncInterface interfaceTwiceObject = new FuncInferFaceTwiceImpl();
interfaceTwiceObject.abstractFun(5);
FuncInterface interfaceSquareObject = new FuncInterfaceSquareImpl();
interfaceSquareObject.abstractFun(5);
}
}
It prints
10
25
Now, what you had to do?
You had to create two separate Classes (in separate new files or
could have made private classes in the same file that of MyClass),
each implementing the abstract method.
Then you instantiated objects of each class and called them
respectively in the main function.
What if this is the only place where you had to call this twice and square thing? You had to make two classes just to use them only once. This effort is too much!!
What if you want to call it without creating new classes and implementing methods in a class?
What if I tell you only provide me the method body, I will do the work for you without you to bother about implementing interface and overriding methods?
Here comes the Lambda magic. Instead of making any impl classes just
head straight towards the main method
Instantiate two objects of FuncInterface providing only method body in Lambda expression.
Call abstract method from objects just like below
public class MyClass {
public static void main(String[] args) {
FuncInterface interfaceTwiceObject = (n) -> System.out.println(2*n);
interfaceTwiceObject.abstractFun(5);
FuncInterface interfaceSquareObject = (n) -> System.out.println(n*n);
interfaceSquareObject.abstractFun(5);
}
}
And boom, the output is
10
25
Just one more time where Lambda saved your day!!
Yes all methods in Java have to be part of a class. You cannot create a method (static or otherwise) which is not associated with a class.
EDIT
Before I answer your question, I will point out that lambda expressions were introduced in Java 8 through the concept of SAM types. In addition, a bit of syntactic sugar was also introduced to facilitate the creation of these types.
When you hear the term "Lambda expression" in Java, you should always remember that they are expressions. Your confusion stems from thinking that lambda expressions evaluate to a pure function not associated with a class or object; well this is simply not the case in Java and I will show you why.
Lambda expressions are not functions
I can now see where your confusion comes from because that article you are reading made a false claim when they say that lambda expression is:
A function that can be created without belonging to any class.
This is simply not true. A lambda expression in Java is not a function. Take the example they give for instance.
interface FuncInterface
{
// An abstract function
void abstractFun(int x);
// A non-abstract (or default) function
default void normalFun()
{
System.out.println("Hello");
}
}
class Test
{
public static void main(String args[])
{
// lambda expression to implement above
// functional interface. This interface
// by default implements abstractFun()
FuncInterface fobj = (int x)->System.out.println(2*x);
// This calls above lambda expression and prints 10.
fobj.abstractFun(5);
}
}
Proof
Now take the comment they have in the main method:
lambda expression to implement above functional interface
From the start they admit that the next line of code implements a functional interface. However functions in Java do not implement interfaces, only classes or other interfaces can do that!
Now, they even go ahead and "call" this function:
This calls above lambda expression and prints 10.
except instead of directly invoking the function (as anyone would if this was really a function), they use the property accessor notation (.) to access the actual method they wanted to call, which means what we have here is not a function, but actually an instance of an anonymous class.
Furthermore, since this object actually contains another method (normalFun), one might ask the question, which one do I use when I want to pass this "function" to another method? This is not a question that is commonly (if ever) asked in the context of lambda functions because there is only one thing to do with a lambda function and that is to call it.
In closing
Java has lambda expressions, not lambda functions.
What makes it a lambda expression is simply the syntactic sugar introduced in Java 8 that uses the () -> { } notation. Unfortunately, many fans of functional programming began associating the term "Lambda function" with objects created using this syntax, and this has led to the confusion you have expressed in your question.
To rehash what I answered previously, all functions in Java are part of a class, and you cannot have a function which is not associated with an object, nor can you create a function outside a class.
HTH

Java: Not a statement

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;
}
}

this and super in java

this and super are keywords aren't they; then how can I use them for passing arguments to constructors the same way as with a method??
In short how is it that both can show such distinct behaviors??
You are correct that both this and super are keywords. The Java language specification defines explicitly how they must behave. The short answer is that these keywords behave specially because the specification says that they must.
According to the specification this can be used a primary expression (only in certain places) or in an explicit constructor invocation.
The keyword this may be used only in the body of an instance method, instance initializer or constructor, or in the initializer of an instance variable of a class. If it appears anywhere else, a compile-time error occurs.
So you can use this as an argument to a function to pass a reference to the current object. However note that you cannot use super in the same way as it is not a primary expression:
public class Program
{
void test(Program p) {}
void run() { test(super); }
public static void main(String[] args)
{
new Program().run();
}
}
Result:
Program.java:5: '.' expected
void run() { test(super); }
You can use super.foo though because this is defined in 15.11 to be valid:
FieldAccess:
Primary . Identifier
super . Identifier
ClassName .super . Identifier
The specification also puts restrictions on how super can be used:
The special forms using the keyword super are valid only in an instance method, instance initializer or constructor, or in the initializer of an instance variable of a class; these are exactly the same situations in which the keyword this may be used (§15.8.3).
The Java language provides specific handling for these two keywords and they are allowed in limited contexts.
Invoking this(...) will result in bytecode that will invoke the corresponding constructor on the current class, while invoking super(...) will result in bytecode that will invoke the corresponding constructor on the supertype.
Java provides special handling for these because their binding is different from that of normal methods (i.e., you want to avoid dynamic invocation, or you would never manage to get the constructor on the supertype).
Every language has to deal with this problem. In C++, for example, you explicitly specify the name of the parent method instead of using super.
I'm not entirely sure what you're asking here, but this is the way the language is designed. The compiler knows that when you do this in a constructor:
super("I'm a string!", 32);
it should find a constructor in the superclass that takes a String and an int as parameters.
From your sub-class you can pass the variables provided to your parent. Examples are better then long explanations so here's a pretty generic example of Extending the Exception Class for your own usage:
public class MyException extends Exception {
public MyException()
{
}
public MyException(String message)
{
super(message);
}
public MyException(String string, Throwable e)
{
super(string, e);
}
}
how is it that these can show such
distinct behaviours
The question doesn't make sense. All keywords have distinct behaviours. That's what they're for.
I am not sure what is the doubt here. This this refers to the reference to the current instance, also when called like this(arg) it calls the corresponding constructor in the current class. Similarly, when super() is called it calls the corresponding constructor in the super class. They can be called only from a constructor.
According to Wikipedia, this and super are keywords, which is how they get away with all their magic, I suppose.

Categories