Does Java automatically save an 'evaluate' statement in a predefined Java variable? - java

Say I perform a simple add/concatenation statement:
variable + newInput
Without setting the calculated value to a new variable, as in:
variable = variable + newInput
or
variable += newInput
Does Java have some sort of specifier to be able to use the computed sum or concatenated string?
Apparently in Python it is automatically saved in the implicit global variable _ -which is implementable like
Print(_)
Is there anything like this in Java?

No. It does not have anything like this. You have to assign the computed value to a variable, otherwise it will be lost and consequently collected by the garbage collector.
The best option is to use a special operator so not to use an extra variable but assign the result to an old one. This is a Shorthand operator.
Variable += NewInput

More than just not saving the result, Java will outright refuse to compile your program if it contains such a line, precisely because the result would be unsaved and unusable if it was allowed:
public class Main
{
public static void main(String[] args)
{
1+2;
}
}
Result:
Main.java:5: error: not a statement
1+2;
^
1 error
Java does not allow arbitrary expressions as statements, and addition expressions are not considered valid Java statements.
The expressions that are allowed as statements by themselves are listed in the JLS:
ExpressionStatement:
StatementExpression ;
StatementExpression:
Assignment
PreIncrementExpression
PreDecrementExpression
PostIncrementExpression
PostDecrementExpression
MethodInvocation
ClassInstanceCreationExpression
Assignment, increment, decrement, method calls, and new Whatever(), all things with side effects or potential side effects. Barring possible side effects of an implicit toString() call, + cannot have side effects, so to catch probable errors, Java forbids addition expressions from being statements.

You can for sure do:
variable + newInput
but the result of that operation must be assigned to a variable, if not, it will get lost...
the most you can get is
variable += newInput
whihch is similar to
variable = variable + newInput

The point is: the + operator in Java simply takes two operands and returns a result (either numerical, or as string concatenation).
Without assigning this result to something (like returning it from a method; or as shown in your example) ... it is like: the operation never takes place.
This operation doesn't have any side effects on its operands; and there is no way of accessing this result.
Beyond that, there is no operator overloading in Java. So it is also not possible to do some black magic that somehow stores the result of operation as side effect. You could theoretically add an agent to the JVM, that intercepts at runtime to do something upon an add operation, but that is more like: "technically possible", but nothing you would do in practical reality.
Other JVM languages, like Scala for example might use it implicitly - the last expression in a method is always returned, even when leaving out the return statement (in scala).

The statement you show is evaluated and nothing is done with it. Unless you bind a variable to the result, the evaluation occurs without effect.
This will not be flagged as an error by the compiler.

Related

Is Java lazy when passing parameters to a method?

I am using this code:
A a = aMap.contains(key) ? aMap.get(key) : createAExpensively(key);
I believe that Java is lazy so if aMap.contains(key)) then the createAExpensively() function is never called.
Then, I stumbled onto the Map.getOrDefault() method. If we instead use:
A a = aMap.getOrDefault(key, createAExpensively(key));
is Java still lazy in calling the createAExpensively() function?
It seems that Java will first create the object A and pass it as a method parameter, based on this question, but I'm not totally sure.
If Java is not lazy when using Map.getOrDefault(), what is the point of that method?
Is Java still lazy in calling the createAExpensively() function?
[in .getOrDefault(key, createAExpensively(key))]
Function parameters are evaluated (from left to right) before actually calling the function. So createAExpensively(key) will be evaluated before calling getOrDefault. This behavior is also known as applicative order evaluation strategy.
If Java is not lazy when using Map.getOrDefault(), what is the point of that method?
It's useful when the default value is not expensive to create,
for example when it's an already computed value or constant.
In that case the Map.getOrDefault(...) call allows a more compact syntax than the ternary operator.
If the default value is expensive to compute,
and if you actually want to put the computed value in the map,
then as of Java 8,
you can use computeIfAbsent:
A a = aMap.computeIfAbsent(key, k -> createAExpensively(k));
Java is not lazy at all. You are using conditional operator to check whether aMap.contains(key). If this is true it will never call createAExpensively(key) but aMap.get(key)
It isn't lazy in that case.
The point of the method is that there's lots of times when the default is a constant or something you've already computed anyway. For example, you might use getOrDefault(key, 0) when you're getting some kind of count and absent keys should be counted as zeroes.
This is called "short-circuit evaluation" rather than lazy evaluation: The JVM is not deferring evaluation of createExpensively(), but rather avoiding it completely if it's not necessary, i.e if the condition holds.
See also the answer to the following question here on StackOverflow:
Java logical operator short-circuiting
It is not lazy at all.
This code
A a = aMap.contains(key) ? aMap.get(key) : createAExpensively(key);
evaulates to
if (aMap.contains(key))
{
a = aMap.get(key);
}
else
{
a = createAExpensively(key);
}

"Local variable is redundant" using Java

Why is the following giving me a "local variable is redundant error"?
public double depreciationAmount() {
double depreciationAmount = (cost * percentDepreciated);
return depreciationAmount;
}
Why is the following giving me a "local variable is redundant error"?
Because you can trivially write this without using a local variable.
public double depreciationAmount() {
return cost * percentDepreciated;
}
Hence the local variable is deemed to be unnecessary / redundant by the checker.
However, I surmise that this is not a compiler error. It might be a compiler warning, or more likely it is a style checker or bug checker warning. It is something you could ignore without any risk to the correctness of your code ... as written.
Also, I would predict that once that the code has been JIT compiled (by a modern Hotspot JIT compiler ...) there would be no performance difference between the two versions.
I won't attempt to address the issue as to whether the warning is appropriate1. If you feel it is inappropriate, then "Local variable is redundant" using Java explains how to suppress it.
1 - Except to say that it is too much to expect current generation style checkers to know when so-called explaining variables are needed. First you'd need to get a statistically significant2 group of developers to agree on measurable3 criteria for when the variables are needed, and when they aren't.
2 - Yea, I know. Abuse of terminology.
3 - They must be measurable, and there needs to be consensus on what the thresholds should be if this is to be implemented by a checker.
Although not the case here, if having a redundant local variable is desired (I've had one time where this was the case - without getting into specifics), here's how to suppress this specific warning.
#SuppressWarnings("UnnecessaryLocalVariable")
public double depreciationAmount() {
double depreciationAmount = (cost * percentDepreciated);
return depreciationAmount;
}
You only use the value of percentDepreciated to return it when you could have just done return (cost * percentDepreciated).
Why is the following giving me a "local variable is redundant error"?
I believe this message is wrong. Your depreciationAmount variable assignment is totally fine. Moreover, I always prefer this kind of assignment before return, because it helps to avoid confusion while debugging.
In this example, the getValue() method returns an expression result, instead of assigning the expression result to a variable.
Now when I use debugger watch, to know the result of an expression, I got a confusion. My program ends with the wrong result and debugger watch values are inconsistent. It would be easy to avoid this, if I would have a variable assigned before the returning expression:
Integer value = 1 + getCounter();
return value;
instead of:
return 1 + getCounter();
Now I can put a breakpoint at the return statement and know what was the result of the expression, before it was returned. Also I do not need the expression in the watch any more, and code will be executed correctly while debugging.
In computer programming, redundant code is source code or compiled code in a computer program that is unnecessary. In the above code, you can simply return:
(cost * percentDepreciated)

Why can I not reference the variable from within a lambda in this case?

I have got the following code, which is somewhat abstracted from a real implementation I had in a Java program:
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String line;
while ((line = bufferedReader.readLine()) != null) {
String lineReference = line;
runLater(() -> consumeString(lineReference));
}
Here I need to use a reference copy for the lambda expression, when I try to use line I get:
Local variables referenced from a lambda expression must be final or effectively final
It seems rather awkward to me, as all I do to fix it is obtain a new reference to the object, this is something the compiler could also figure out by itself.
So I would say line is effectively final here, as it only gets the assignment in the loop and nowhere else.
Could anyone shed some more light on this and explain why exactly it is needed here and why the compile cannot fix it?
So I would say line is effectively final here, as it only gets the assignment in the loop and nowhere else.
No, it's not final because during the variable's lifetime it is getting assigned a new value on every loop iteration. This is the complete opposite of final.
I get: 'Local variables referenced from a lambda expression must be final or effectively final'. It seems rather awkward to me.
Consider this: You're passing the lambda to runLater(...). When the lambda finally executes, which value of line should it use? The value it had when the lambda was created, or the value it had when the lambda executed?
The rule is that lambdas (appear to) use the current value at time of lambda execution. They do not (appear to) create a copy of the variable. Now, how is this rule implemented in practice?
If line is a static field, it's easy because there is no state for the lambda to capture. The lambda can read the current value of the field whenever it needs to, just as any other code can.
If line is an instance field, that's also fairly easy. The lambda can capture the reference to the object in a private hidden field in each lambda object, and access the line field through that.
If line is a local variable within a method (as it is in your example), this is suddenly not easy. At an implementation level, the lambda expression is in a completely different method, and there is no easy way for outside code to share access to the variable which only exists within the one method.
To enable access to the local variable, the compiler would have to box the variable into some hidden, mutable holder object (such as a 1-element array) so that the holder object could be referenced from both the enclosing method and the lambda, giving them both access to the variable within.
Although that solution would technically work, the behavior it achieves would be undesirable for a bundle of reasons. Allocating the holder object would give local variables an unnatural performance characteristic which would not be obvious from reading the code. (Merely defining a lambda that used a local variable would make the variable slower throughout the method.) Worse than that, it would introduce subtle race conditions into otherwise simple code, depending on when the lambda is executed. In your example, by the time the lambda executes, any number of loop iterations could have happened, or the method might have returned, so the line variable could have any value or no defined value, and almost certainly wouldn't have the value you wanted. So in practice you'd still need the separate, unchanging lineReference variable! The only difference is that the compiler wouldn't require you do to that, so it would allow you to write broken code. Since the lambda could ultimately execute on a different thread, this would also introduce subtle concurrency and thread visibility complexity to local variables, which would require the language to allow the volatile modifier on local variables, and other bother.
So, for the lambda to see the current changing values of local variables would introduce a lot of fuss (and no advantages since you can do the mutable holder trick manually if you ever need to). Instead, the language says no to the whole kerfuffle by simply demanding that the variable be final (or effectively final). That way, the lambda can capture the value of the local variable at lambda creation time, and it doesn't need to worry about detecting changes because it knows there can't be any.
This is something the compiler could also figure out by itself
It did figure it out, which is why it disallows it. The lineReference variable is of absolutely no benefit to the compiler, which could easily capture the current value of line for use in the lambda at each lambda object's creation time. But since the lambda wouldn't detect changes to the variable (which would be impractical and undesirable for the reasons explained above), the subtle difference between capture of fields and capture of locals would be confusing. The "final or effectively final" rule is for the programmer's benefit: it prevents you from wondering why changes to a variable don't appear within a lambda, by preventing you from changing them at all. Here's an example of what would happen without that rule:
String field = "A";
void foo() {
String local = "A";
Runnable r = () -> System.out.println(field + local);
field = "B";
local = "B";
r.run(); // output: "BA"
}
That confusion goes away if any local variables referenced within the lambda are (effectively) final.
In your code, lineReference is effectively final. Its value is assigned exactly once during its lifetime, before it goes out of scope at the end of each loop iteration, which is why you can use it in the lambda.
There is an alternative arrangement of your loop possible by declaring line inside the loop body:
for (;;) {
String line = bufferedReader.readLine();
if (line == null) break;
runLater(() -> consumeString(line));
}
This is allowed because line now goes out of scope at the end of each loop iteration. Each iteration effectively has a fresh variable, assigned exactly once. (However, at a low level the variable is still stored in the same CPU register, so it's not like it has to be repeatedly "created" and "destroyed". What I mean is, there is happily no extra cost to declaring variables inside a loop like this, so it's fine.)
Note: All this is not unique to lambdas. It also applies identically to any classes declared lexically inside the method, from which lambdas inherited the rules.
Note 2: It could be argued that lambdas would be simpler if they followed the rule of always capturing the values of variables they use at lambda creation time. Then there would be no difference in behavior between fields and locals, and no need for the "final or effectively final" rule because it would be well-established that lambdas don't see changes made after lambda creation time. But this rule would have its own uglinesses. As one example, for an instance field x accessed within a lambda, there would be a difference between the behavior of reading x (capturing final value of x) and this.x (capturing final value of this, seeing its field x changing). Language design is hard.
If you would use line instead of lineReference in the lambda expression, you would be passing to your runLater method a lambda expression that would execute consumeString on a String referred by line.
But line keeps changing as you assign new lines to it. When you finally execute the method of the functional interface returned by the lambda expression, only then will it get the current value of line and use it in the call to consumeString. At this point the value of line would not be the same as it was when you passed the lambda expression to the runLater method.

Are there any guarantees when modifying arguments during method invocation?

In Java when passing arguments to a method and modifying the passed arguments during the method call is it guaranteed that the result is what is expected?
E.g.
a.method(++i); etc
Is it guaranteed for instance that inside method the variable i will have the updated
value?
Or a.method(i++) Will method get the value of i after incrementing or before?
Also same for all similar cases.
I kind of remember this is forbidden in C++ as implementation specific but perhaps I remember wrong.
The java language specification for prefix/postfix increment/decrement operators:
Prefix: http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.15.1.
... the value 1 is added to the value of the variable and the sum is stored back into the variable ... The value of the prefix increment expression is the value of the
variable after the new value is stored.
Postfix: http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.14.2
... the value 1 is added to the value of the variable and the sum is stored back into the variable ... The value of the postfix increment expression is the value of the variable before the new value is stored.
I think it's pretty clear. The function will get the incremented value in the prefix case, and not in the postfix case.
The expression ++i is evaluated before the method is called.
From the Java Language Specification's section "Runtime evaluation of method invocation":
... Second, the argument expressions are evaluated. ... Fifth, a new activation frame is created, synchronization is performed if necessary, and control is transferred to the method code.
And from the Java Language Specification's section "Prefix increment operator":
The value of the prefix increment expression is the value of the variable after the new value is stored.
No problem in Java, method will receive the updated value.

Definition of "expression"

In my Java book, it says that "an expression is a statement that can convey a return value." This is different than my traditional understanding. I thought an expression DOES return a value. Not CAN return a value.
this is from Sams Teach Yourself Java in 21 Days.
A mathematical expression always returns something, but a Java expression doesn't have to. The Java Specification defines what exactly is meant by the term expression in the Java language. Another difference is that expressions can, and often do, have side effects in Java. A side effect is pretty much anything that happens other than returning a value.
Quoting the Java Language Specification:
Much of the work in a program is done by evaluating expressions, either for their side effects, such as assignments to variables, or for their values, which can be used as arguments or operands in larger expressions, or to affect the execution sequence in statements, or both.
For example system.out.println("Hello World"); doesn't return a value, but it does print Hello World to the output stream. This process of outputting data is a side effect of calling println. Functional languages, in contrast, attempt to minimize dependence on side effects and stick more closely to the mathematical definition of an expression.
Quoting from the JLS again, here is the BNF grammar for an expression:
Primary:
PrimaryNoNewArray
ArrayCreationExpression
PrimaryNoNewArray:
Literal
Type . class
void . class
this
ClassName.this
( Expression )
ClassInstanceCreationExpression
FieldAccess
MethodInvocation
ArrayAccess
You can see that a MethodInvocation is an expansion of PrimaryNoNewArray, which is an expansion of Primary (expression).
Your understanding is incomplete. In Java, an expression could return a value, and it could terminate due to an exception. Similar situations arise in other languages which support exceptions, and more generally. (For instance, in the C language, division by zero causes the current expression evaluation to terminate without returning a value.)
Another explanation is that (according to the JLS), a method invocation expression like System.err.println("hello") can deliver a notional void value to its context, and this really means that it is delivering no value.
I don't think this second explanation is sound. We start with an "expression" that is specified as delivering a void value. Then we are argue that since the void value is in reality not a value, the expression is delivering nothing. Finally, we say it is an expression that delivers no value.
A simpler explanation for this example is that an "expression" that delivers "void" is not really an expression in the intuitive sense. Certainly, in Java you cannot use a void-delivering MethodInvocation expression where a non-void-delivering expression is required. And you can't use a non-void-delivering expression as a Statement.
Alternatively, we can stick with the JLS treatment and say that the "void" value really is a value ... even though you can't ever do anything with it. By this argument, System.err.println("Hi") is returning a value after all.
Ouch... This doesn't seem like a very good book :(
An expression either has a type and can be evaluated to yield a value of that type, or is of void type and can be evaluated to yield nothing. The JLS also says an expression can evaluate to a variable, but the variable in turn has a type and a value. For example, 1 + 1 is an expression.
A statement, on the other hand, is composed of expressions but doesn't have a type or a value itself. For example, int x = 1 + 1; has no value. It wouldn't make sense in Java to say something like System.out.println(int x = 1 + 1;);
The method public void foo(); does not return anything, thus the expression foo() does not return anything. But if the method was public int foo(), then it would. Thus it could return something, but doesn't necessarily have to. From the Java spec:
An expression denotes nothing if and only if it is a method invocation
that invokes a method that does not return a value, that is, a method
declared void. Such an expression can be used only as an expression
statement, because every other context in which an expression can
appear requires the expression to denote something. An expression
statement that is a method invocation may also invoke a method that
produces a result; in this case the value returned by the method is
quietly discarded.

Categories