Are there any guarantees when modifying arguments during method invocation? - java

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.

Related

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

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.

Run Java without Array Bounds checking, Cast checking, etc

I have a Java program that does many small array operations. I've run it and verified that it produces no errors, but it is slower than expected. I'm assuming a lot of this slowdown is related to checking array bounds, etc.
Is there a way to disable all error checking so I can run my program faster (at risk that it just crashes, rather then generates an intelligible error)?
No, this is not possible. The Java Language Specification describes the circumstances under which casts and array accesses throw exceptions, but makes no mention of a mechanism to disable this behaviour.
Throwing of ClassCastException is described in JLS Section 15.6:
A cast expression (ยง15.16) throws a ClassCastException if a cast is found to be impermissible at run time.
Array bounds checking is described in JLS Section 15.10.4:
At run time, evaluation of an array access expression behaves as follows:
First, the array reference expression is evaluated. If this evaluation completes abruptly, then the array access completes abruptly for the same reason and the index expression is not evaluated.
Otherwise, the index expression is evaluated. If this evaluation completes abruptly, then the array access completes abruptly for the same reason.
Otherwise, if the value of the array reference expression is null, then a NullPointerException is thrown.
Otherwise, the value of the array reference expression indeed refers to an array. If the value of the index expression is less than zero, or greater than or equal to the array's length, then an ArrayIndexOutOfBoundsException is thrown.
Otherwise, the result of the array access is the variable of type T, within the array, selected by the value of the index expression.
No this is not possible as this would break the JVM in case of error.

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.

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.

In Java, is null an existing object on the heap?

In Java, is null an existing object on the heap?
I'm trying to understand the difference between an uninitialized local variable (what does not compile) and one initialized with null (what compiles).
See here:
The Java IAQ:
Infrequently Answered Questions: Is null an Object?
Or, to save you the clicking, the answer is no, it is not an object. Being null means that no object is referenced.
This question highlights the connection between scope and definite assignment. If you step through the code below in a debugger, you can see several features as you break on each line:
No breakpoint possible; i is not in scope.
i is in scope, but "not a known variable in the current context."
The reference i has been assigned, and it has the value null.
The reference i has the value 1, which will be incremented after line 4.
Listing:
Integer i;
i = null;
i = Integer.valueOf(1);
i++;
Addendum:
So, what's the difference between null and uninitialized?
Prior to definite assignment, a local variable's value is inaccessible; any attempt to access the value is rejected at compile-time. Once a definite value is assigned, even null, that value can be accessed. This is a critical security feature in Java. In some languages, an uninitialized variable may reference values in memory left by a previous process.
Addendum: The content of a frame's local variables prior to initialization is unspecified. The bytecode verifier precludes bytecode that accesses uninitialized memory, but deviant bytecode is possible.
a local variable that hasn't been assigned yet, probably points to null too. I'm not a JVM expert, but that seems to be the logical choice.
so compiler checks for you to make sure you assigned something to the variable. other than that there's no difference. at runtime local variables not initialized yet are assigned to null.
Null is NOT an object. In fact it is the opposite of an object, and why you can't make method calls against a reference pointing at null. If you really must know what null is you can think of it as a something like zero. In fact a reference that points to null doesn't take up anymore memory, ie. zero. It has no value so it's a reference that doesn't refer to any object.
In Java you have to initialize a variable before you can use it. For reasons of history Java doesn't want you to assume values so the compiler forces you to assign a value to it. Part of the reasons for this is the bugs and security problems that C caused because it didn't initialize values or force you to do it before they were used. Java does initialize some values for primitives, and instance variables: 0, 0.0, false, and null etc, but for local variables you have to give it a value. It's for your own protection. :-)

Categories